authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-15 09:51:57-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-05-15 09:51:57-07:00
log2286c19c20897727825a6fd8dd63de1ada6724ee
tree1d8a36c24bd566626af7944c535364ac18f55ab9
parentde6cafa80fba3c1fb93bf82b76c1efffbc61bf98
parentcea9ac772a518ff249d47fc2cb7b2776c786ac07
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #15628 from jacobly0/x86_64-behavior


27 files changed, 2115 insertions(+), 719 deletions(-)

src/arch/x86_64/CodeGen.zig+1198-381
......@@ -1079,9 +1079,9 @@ fn asmSetccRegister(self: *Self, reg: Register, cc: bits.Condition) !void {
10791079 .fixes = Mir.Inst.Fixes.fromCondition(cc),
10801080 .r1 = reg,
10811081 } },
1082 .z_and_np, .nz_or_p => .{ .r_scratch = .{
1082 .z_and_np, .nz_or_p => .{ .rr = .{
10831083 .r1 = reg,
1084 .scratch_reg = (try self.register_manager.allocReg(null, gp)).to8(),
1084 .r2 = (try self.register_manager.allocReg(null, gp)).to8(),
10851085 } },
10861086 },
10871087 });
......@@ -1120,8 +1120,8 @@ fn asmSetccMemory(self: *Self, m: Memory, cc: bits.Condition) !void {
11201120 .fixes = Mir.Inst.Fixes.fromCondition(cc),
11211121 .payload = payload,
11221122 } },
1123 .z_and_np, .nz_or_p => .{ .x_scratch = .{
1124 .scratch_reg = (try self.register_manager.allocReg(null, gp)).to8(),
1123 .z_and_np, .nz_or_p => .{ .rx = .{
1124 .r1 = (try self.register_manager.allocReg(null, gp)).to8(),
11251125 .payload = payload,
11261126 } },
11271127 },
......@@ -1460,6 +1460,15 @@ fn asmMemoryRegister(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, reg: Regist
14601460}
14611461
14621462fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, imm: Immediate) !void {
1463 const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
1464 .signed => |s| @bitCast(u32, s),
1465 .unsigned => |u| @intCast(u32, u),
1466 } });
1467 assert(payload + 1 == switch (m) {
1468 .sib => try self.addExtra(Mir.MemorySib.encode(m)),
1469 .rip => try self.addExtra(Mir.MemoryRip.encode(m)),
1470 else => unreachable,
1471 });
14631472 _ = try self.addInst(.{
14641473 .tag = tag[1],
14651474 .ops = switch (m) {
......@@ -1475,17 +1484,9 @@ fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, imm: Immed
14751484 },
14761485 .data = .{ .x = .{
14771486 .fixes = tag[0],
1478 .payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
1479 .signed => |s| @bitCast(u32, s),
1480 .unsigned => |u| @intCast(u32, u),
1481 } }),
1487 .payload = payload,
14821488 } },
14831489 });
1484 _ = switch (m) {
1485 .sib => try self.addExtra(Mir.MemorySib.encode(m)),
1486 .rip => try self.addExtra(Mir.MemoryRip.encode(m)),
1487 else => unreachable,
1488 };
14891490}
14901491
14911492fn asmMemoryRegisterRegister(
......@@ -1549,7 +1550,9 @@ fn gen(self: *Self) InnerError!void {
15491550 const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();
15501551 try self.asmRegisterRegister(.{ ._, .mov }, .rbp, .rsp);
15511552 const backpatch_frame_align = try self.asmPlaceholder();
1553 const backpatch_frame_align_extra = try self.asmPlaceholder();
15521554 const backpatch_stack_alloc = try self.asmPlaceholder();
1555 const backpatch_stack_alloc_extra = try self.asmPlaceholder();
15531556
15541557 switch (self.ret_mcv.long) {
15551558 .none, .unreach => {},
......@@ -1598,24 +1601,67 @@ fn gen(self: *Self) InnerError!void {
15981601 const need_stack_adjust = frame_layout.stack_adjust > 0;
15991602 const need_save_reg = frame_layout.save_reg_list.count() > 0;
16001603 if (need_frame_align) {
1604 const page_align = @as(u32, math.maxInt(u32)) << 12;
16011605 self.mir_instructions.set(backpatch_frame_align, .{
16021606 .tag = .@"and",
16031607 .ops = .ri_s,
16041608 .data = .{ .ri = .{
16051609 .r1 = .rsp,
1606 .i = frame_layout.stack_mask,
1610 .i = @max(frame_layout.stack_mask, page_align),
16071611 } },
16081612 });
1613 if (frame_layout.stack_mask < page_align) {
1614 self.mir_instructions.set(backpatch_frame_align_extra, .{
1615 .tag = .pseudo,
1616 .ops = .pseudo_probe_align_ri_s,
1617 .data = .{ .ri = .{
1618 .r1 = .rsp,
1619 .i = ~frame_layout.stack_mask & page_align,
1620 } },
1621 });
1622 }
16091623 }
16101624 if (need_stack_adjust) {
1611 self.mir_instructions.set(backpatch_stack_alloc, .{
1612 .tag = .sub,
1613 .ops = .ri_s,
1614 .data = .{ .ri = .{
1615 .r1 = .rsp,
1616 .i = frame_layout.stack_adjust,
1617 } },
1618 });
1625 const page_size: u32 = 1 << 12;
1626 if (frame_layout.stack_adjust <= page_size) {
1627 self.mir_instructions.set(backpatch_stack_alloc, .{
1628 .tag = .sub,
1629 .ops = .ri_s,
1630 .data = .{ .ri = .{
1631 .r1 = .rsp,
1632 .i = frame_layout.stack_adjust,
1633 } },
1634 });
1635 } else if (frame_layout.stack_adjust <
1636 page_size * Lower.pseudo_probe_adjust_unrolled_max_insts)
1637 {
1638 self.mir_instructions.set(backpatch_stack_alloc, .{
1639 .tag = .pseudo,
1640 .ops = .pseudo_probe_adjust_unrolled_ri_s,
1641 .data = .{ .ri = .{
1642 .r1 = .rsp,
1643 .i = frame_layout.stack_adjust,
1644 } },
1645 });
1646 } else {
1647 self.mir_instructions.set(backpatch_stack_alloc, .{
1648 .tag = .pseudo,
1649 .ops = .pseudo_probe_adjust_setup_rri_s,
1650 .data = .{ .rri = .{
1651 .r1 = .rsp,
1652 .r2 = .rax,
1653 .i = frame_layout.stack_adjust,
1654 } },
1655 });
1656 self.mir_instructions.set(backpatch_stack_alloc_extra, .{
1657 .tag = .pseudo,
1658 .ops = .pseudo_probe_adjust_loop_rr,
1659 .data = .{ .rr = .{
1660 .r1 = .rsp,
1661 .r2 = .rax,
1662 } },
1663 });
1664 }
16191665 }
16201666 if (need_frame_align or need_stack_adjust) {
16211667 self.mir_instructions.set(backpatch_stack_dealloc, .{
......@@ -2215,11 +2261,11 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b
22152261 },
22162262 .Vector => switch (ty.childType().zigTypeTag()) {
22172263 .Float => switch (ty.childType().floatBits(self.target.*)) {
2218 16, 32, 64 => if (self.hasFeature(.avx)) 32 else 16,
2219 80, 128 => break :need_mem,
2264 16, 32, 64, 128 => if (self.hasFeature(.avx)) 32 else 16,
2265 80 => break :need_mem,
22202266 else => unreachable,
22212267 },
2222 else => break :need_mem,
2268 else => if (self.hasFeature(.avx)) 32 else 16,
22232269 },
22242270 else => 8,
22252271 })) {
......@@ -2455,12 +2501,12 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
24552501 }
24562502 } else if (src_bits == 64 and dst_bits == 32) {
24572503 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
2458 .{ .v_, .cvtsd2ss },
2504 .{ .v_ss, .cvtsd2 },
24592505 dst_reg,
24602506 dst_reg,
24612507 src_mcv.mem(.qword),
24622508 ) else try self.asmRegisterRegisterRegister(
2463 .{ .v_, .cvtsd2ss },
2509 .{ .v_ss, .cvtsd2 },
24642510 dst_reg,
24652511 dst_reg,
24662512 (if (src_mcv.isRegister())
......@@ -2468,11 +2514,11 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
24682514 else
24692515 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
24702516 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2471 .{ ._, .cvtsd2ss },
2517 .{ ._ss, .cvtsd2 },
24722518 dst_reg,
24732519 src_mcv.mem(.qword),
24742520 ) else try self.asmRegisterRegister(
2475 .{ ._, .cvtsd2ss },
2521 .{ ._ss, .cvtsd2 },
24762522 dst_reg,
24772523 (if (src_mcv.isRegister())
24782524 src_mcv.getReg().?
......@@ -2506,22 +2552,22 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
25062552 src_mcv.getReg().?
25072553 else
25082554 try self.copyToTmpRegister(src_ty, src_mcv);
2509 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, mat_src_reg.to128());
2555 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, mat_src_reg.to128());
25102556 switch (dst_bits) {
25112557 32 => {},
2512 64 => try self.asmRegisterRegisterRegister(.{ .v_, .cvtss2sd }, dst_reg, dst_reg, dst_reg),
2558 64 => try self.asmRegisterRegisterRegister(.{ .v_sd, .cvtss2 }, dst_reg, dst_reg, dst_reg),
25132559 else => return self.fail("TODO implement airFpext from {} to {}", .{
25142560 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
25152561 }),
25162562 }
25172563 } else if (src_bits == 32 and dst_bits == 64) {
25182564 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
2519 .{ .v_, .cvtss2sd },
2565 .{ .v_sd, .cvtss2 },
25202566 dst_reg,
25212567 dst_reg,
25222568 src_mcv.mem(.dword),
25232569 ) else try self.asmRegisterRegisterRegister(
2524 .{ .v_, .cvtss2sd },
2570 .{ .v_sd, .cvtss2 },
25252571 dst_reg,
25262572 dst_reg,
25272573 (if (src_mcv.isRegister())
......@@ -2529,11 +2575,11 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
25292575 else
25302576 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
25312577 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2532 .{ ._, .cvtss2sd },
2578 .{ ._sd, .cvtss2 },
25332579 dst_reg,
25342580 src_mcv.mem(.dword),
25352581 ) else try self.asmRegisterRegister(
2536 .{ ._, .cvtss2sd },
2582 .{ ._sd, .cvtss2 },
25372583 dst_reg,
25382584 (if (src_mcv.isRegister())
25392585 src_mcv.getReg().?
......@@ -2754,8 +2800,10 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
27542800 const result = result: {
27552801 const tag = self.air.instructions.items(.tag)[inst];
27562802 const dst_ty = self.air.typeOfIndex(inst);
2757 if (dst_ty.zigTypeTag() == .Float)
2758 break :result try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs);
2803 switch (dst_ty.zigTypeTag()) {
2804 .Float, .Vector => break :result try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs),
2805 else => {},
2806 }
27592807
27602808 const dst_info = dst_ty.intInfo(self.target.*);
27612809 var src_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dst_info.signedness) {
......@@ -3421,14 +3469,17 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
34213469 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
34223470 }
34233471
3424 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
3472 const dst_mcv: MCValue = if (src_mcv.isRegister() and
3473 self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
34253474 src_mcv
3475 else if (self.liveness.isUnused(inst))
3476 .{ .register = try self.copyToTmpRegister(dst_ty, src_mcv) }
34263477 else
34273478 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
34283479
34293480 const pl_ty = dst_ty.childType();
34303481 const pl_abi_size = @intCast(i32, pl_ty.abiSize(self.target.*));
3431 try self.genSetMem(.{ .reg = dst_mcv.register }, pl_abi_size, Type.bool, .{ .immediate = 1 });
3482 try self.genSetMem(.{ .reg = dst_mcv.getReg().? }, pl_abi_size, Type.bool, .{ .immediate = 1 });
34323483 break :result if (self.liveness.isUnused(inst)) .unreach else dst_mcv;
34333484 };
34343485 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -4177,9 +4228,18 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
41774228
41784229 const src_bits = src_ty.bitSize(self.target.*);
41794230 if (self.hasFeature(.lzcnt)) {
4180 if (src_bits <= 64) {
4231 if (src_bits <= 8) {
4232 const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv);
4233 try self.truncateRegister(src_ty, wide_reg);
4234 try self.genBinOpMir(.{ ._, .lzcnt }, Type.u32, dst_mcv, .{ .register = wide_reg });
4235 try self.genBinOpMir(
4236 .{ ._, .sub },
4237 dst_ty,
4238 dst_mcv,
4239 .{ .immediate = 8 + self.regExtraBits(src_ty) },
4240 );
4241 } else if (src_bits <= 64) {
41814242 try self.genBinOpMir(.{ ._, .lzcnt }, src_ty, dst_mcv, mat_src_mcv);
4182
41834243 const extra_bits = self.regExtraBits(src_ty);
41844244 if (extra_bits > 0) {
41854245 try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .immediate = extra_bits });
......@@ -4218,7 +4278,17 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
42184278 const imm_reg = try self.copyToTmpRegister(dst_ty, .{
42194279 .immediate = src_bits ^ (src_bits - 1),
42204280 });
4221 try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv);
4281 const imm_lock = self.register_manager.lockRegAssumeUnused(imm_reg);
4282 defer self.register_manager.unlockReg(imm_lock);
4283
4284 if (src_bits <= 8) {
4285 const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv);
4286 const wide_lock = self.register_manager.lockRegAssumeUnused(wide_reg);
4287 defer self.register_manager.unlockReg(wide_lock);
4288
4289 try self.truncateRegister(src_ty, wide_reg);
4290 try self.genBinOpMir(.{ ._, .bsr }, Type.u16, dst_mcv, .{ .register = wide_reg });
4291 } else try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv);
42224292
42234293 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2);
42244294 try self.asmCmovccRegisterRegister(
......@@ -4232,7 +4302,20 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
42324302 const imm_reg = try self.copyToTmpRegister(dst_ty, .{
42334303 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - self.regBitSize(dst_ty)),
42344304 });
4235 try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv);
4305 const imm_lock = self.register_manager.lockRegAssumeUnused(imm_reg);
4306 defer self.register_manager.unlockReg(imm_lock);
4307
4308 const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv);
4309 const wide_lock = self.register_manager.lockRegAssumeUnused(wide_reg);
4310 defer self.register_manager.unlockReg(wide_lock);
4311
4312 try self.truncateRegister(src_ty, wide_reg);
4313 try self.genBinOpMir(
4314 .{ ._, .bsr },
4315 if (src_bits <= 8) Type.u16 else src_ty,
4316 dst_mcv,
4317 .{ .register = wide_reg },
4318 );
42364319
42374320 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2);
42384321 try self.asmCmovccRegisterRegister(
......@@ -4274,24 +4357,25 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
42744357
42754358 if (self.hasFeature(.bmi)) {
42764359 if (src_bits <= 64) {
4277 const extra_bits = self.regExtraBits(src_ty);
4360 const extra_bits = self.regExtraBits(src_ty) + @as(u64, if (src_bits <= 8) 8 else 0);
4361 const wide_ty = if (src_bits <= 8) Type.u16 else src_ty;
42784362 const masked_mcv = if (extra_bits > 0) masked: {
42794363 const tmp_mcv = tmp: {
42804364 if (src_mcv.isImmediate() or self.liveness.operandDies(inst, 0))
42814365 break :tmp src_mcv;
4282 try self.genSetReg(dst_reg, src_ty, src_mcv);
4366 try self.genSetReg(dst_reg, wide_ty, src_mcv);
42834367 break :tmp dst_mcv;
42844368 };
42854369 try self.genBinOpMir(
42864370 .{ ._, .@"or" },
4287 src_ty,
4371 wide_ty,
42884372 tmp_mcv,
42894373 .{ .immediate = (@as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - extra_bits)) <<
42904374 @intCast(u6, src_bits) },
42914375 );
42924376 break :masked tmp_mcv;
42934377 } else mat_src_mcv;
4294 try self.genBinOpMir(.{ ._, .tzcnt }, src_ty, dst_mcv, masked_mcv);
4378 try self.genBinOpMir(.{ ._, .tzcnt }, wide_ty, dst_mcv, masked_mcv);
42954379 } else if (src_bits <= 128) {
42964380 const tmp_reg = try self.register_manager.allocReg(null, gp);
42974381 const tmp_mcv = MCValue{ .register = tmp_reg };
......@@ -4320,7 +4404,17 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
43204404 return self.fail("TODO airCtz of {}", .{src_ty.fmt(self.bin_file.options.module.?)});
43214405
43224406 const width_reg = try self.copyToTmpRegister(dst_ty, .{ .immediate = src_bits });
4323 try self.genBinOpMir(.{ ._, .bsf }, src_ty, dst_mcv, mat_src_mcv);
4407 const width_lock = self.register_manager.lockRegAssumeUnused(width_reg);
4408 defer self.register_manager.unlockReg(width_lock);
4409
4410 if (src_bits <= 8 or !math.isPowerOfTwo(src_bits)) {
4411 const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv);
4412 const wide_lock = self.register_manager.lockRegAssumeUnused(wide_reg);
4413 defer self.register_manager.unlockReg(wide_lock);
4414
4415 try self.truncateRegister(src_ty, wide_reg);
4416 try self.genBinOpMir(.{ ._, .bsf }, Type.u16, dst_mcv, .{ .register = wide_reg });
4417 } else try self.genBinOpMir(.{ ._, .bsf }, src_ty, dst_mcv, mat_src_mcv);
43244418
43254419 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2);
43264420 try self.asmCmovccRegisterRegister(
......@@ -4632,61 +4726,136 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
46324726}
46334727
46344728fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
4729 const tag = self.air.instructions.items(.tag)[inst];
46354730 const un_op = self.air.instructions.items(.data)[inst].un_op;
46364731 const ty = self.air.typeOf(un_op);
4637 const ty_bits = ty.floatBits(self.target.*);
4732 const abi_size: u32 = switch (ty.abiSize(self.target.*)) {
4733 1...16 => 16,
4734 17...32 => 32,
4735 else => return self.fail("TODO implement airFloatSign for {}", .{
4736 ty.fmt(self.bin_file.options.module.?),
4737 }),
4738 };
4739 const scalar_bits = ty.scalarType().floatBits(self.target.*);
4740
4741 const src_mcv = try self.resolveInst(un_op);
4742 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
4743 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
4744
4745 const dst_mcv: MCValue = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv))
4746 src_mcv
4747 else if (self.hasFeature(.avx))
4748 .{ .register = try self.register_manager.allocReg(inst, sse) }
4749 else
4750 try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
4751 const dst_reg = dst_mcv.getReg().?;
4752 const dst_lock = self.register_manager.lockReg(dst_reg);
4753 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
46384754
46394755 var arena = std.heap.ArenaAllocator.init(self.gpa);
46404756 defer arena.deinit();
46414757
4642 const ExpectedContents = union {
4643 f16: Value.Payload.Float_16,
4644 f32: Value.Payload.Float_32,
4645 f64: Value.Payload.Float_64,
4646 f80: Value.Payload.Float_80,
4647 f128: Value.Payload.Float_128,
4758 const ExpectedContents = struct {
4759 scalar: union {
4760 i64: Value.Payload.I64,
4761 big: struct {
4762 limbs: [
4763 @max(
4764 std.math.big.int.Managed.default_capacity,
4765 std.math.big.int.calcTwosCompLimbCount(128),
4766 )
4767 ]std.math.big.Limb,
4768 pl: Value.Payload.BigInt,
4769 },
4770 },
4771 repeated: Value.Payload.SubValue,
46484772 };
46494773 var stack align(@alignOf(ExpectedContents)) =
46504774 std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
46514775
4776 var int_pl = Type.Payload.Bits{
4777 .base = .{ .tag = .int_signed },
4778 .data = scalar_bits,
4779 };
46524780 var vec_pl = Type.Payload.Array{
46534781 .base = .{ .tag = .vector },
46544782 .data = .{
4655 .len = @divExact(128, ty_bits),
4656 .elem_type = ty,
4783 .len = @divExact(abi_size * 8, scalar_bits),
4784 .elem_type = Type.initPayload(&int_pl.base),
46574785 },
46584786 };
46594787 const vec_ty = Type.initPayload(&vec_pl.base);
4660
4661 var sign_pl = Value.Payload.SubValue{
4662 .base = .{ .tag = .repeated },
4663 .data = try Value.floatToValue(-0.0, stack.get(), ty, self.target.*),
4788 const sign_val = switch (tag) {
4789 .neg => try vec_ty.minInt(stack.get(), self.target.*),
4790 .fabs => try vec_ty.maxInt(stack.get(), self.target.*),
4791 else => unreachable,
46644792 };
4665 const sign_val = Value.initPayload(&sign_pl.base);
46664793
46674794 const sign_mcv = try self.genTypedValue(.{ .ty = vec_ty, .val = sign_val });
4668
4669 const src_mcv = try self.resolveInst(un_op);
4670 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv))
4671 src_mcv
4795 const sign_mem = if (sign_mcv.isMemory())
4796 sign_mcv.mem(Memory.PtrSize.fromSize(abi_size))
46724797 else
4673 try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
4674 const dst_lock = self.register_manager.lockReg(dst_mcv.register);
4675 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
4798 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
4799 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, sign_mcv.address()) },
4800 });
46764801
4677 const tag = self.air.instructions.items(.tag)[inst];
4678 try self.genBinOpMir(switch (ty_bits) {
4679 // No point using an extra prefix byte for *pd which performs the same operation.
4680 16, 32, 64, 128 => switch (tag) {
4681 .neg => .{ ._ps, .xor },
4682 .fabs => .{ ._ps, .andn },
4802 if (self.hasFeature(.avx)) try self.asmRegisterRegisterMemory(
4803 switch (scalar_bits) {
4804 16, 128 => if (abi_size <= 16 or self.hasFeature(.avx2)) switch (tag) {
4805 .neg => .{ .vp_, .xor },
4806 .fabs => .{ .vp_, .@"and" },
4807 else => unreachable,
4808 } else switch (tag) {
4809 .neg => .{ .v_ps, .xor },
4810 .fabs => .{ .v_ps, .@"and" },
4811 else => unreachable,
4812 },
4813 32 => switch (tag) {
4814 .neg => .{ .v_ps, .xor },
4815 .fabs => .{ .v_ps, .@"and" },
4816 else => unreachable,
4817 },
4818 64 => switch (tag) {
4819 .neg => .{ .v_pd, .xor },
4820 .fabs => .{ .v_pd, .@"and" },
4821 else => unreachable,
4822 },
4823 80 => return self.fail("TODO implement airFloatSign for {}", .{
4824 ty.fmt(self.bin_file.options.module.?),
4825 }),
46834826 else => unreachable,
46844827 },
4685 80 => return self.fail("TODO implement airFloatSign for {}", .{
4686 ty.fmt(self.bin_file.options.module.?),
4687 }),
4688 else => unreachable,
4689 }, vec_ty, dst_mcv, sign_mcv);
4828 registerAlias(dst_reg, abi_size),
4829 registerAlias(if (src_mcv.isRegister())
4830 src_mcv.getReg().?
4831 else
4832 try self.copyToTmpRegister(ty, src_mcv), abi_size),
4833 sign_mem,
4834 ) else try self.asmRegisterMemory(
4835 switch (scalar_bits) {
4836 16, 128 => switch (tag) {
4837 .neg => .{ .p_, .xor },
4838 .fabs => .{ .p_, .@"and" },
4839 else => unreachable,
4840 },
4841 32 => switch (tag) {
4842 .neg => .{ ._ps, .xor },
4843 .fabs => .{ ._ps, .@"and" },
4844 else => unreachable,
4845 },
4846 64 => switch (tag) {
4847 .neg => .{ ._pd, .xor },
4848 .fabs => .{ ._pd, .@"and" },
4849 else => unreachable,
4850 },
4851 80 => return self.fail("TODO implement airFloatSign for {}", .{
4852 ty.fmt(self.bin_file.options.module.?),
4853 }),
4854 else => unreachable,
4855 },
4856 registerAlias(dst_reg, abi_size),
4857 sign_mem,
4858 );
46904859 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
46914860}
46924861
......@@ -4740,7 +4909,6 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
47404909 })) |tag| tag else return self.fail("TODO implement genRound for {}", .{
47414910 ty.fmt(self.bin_file.options.module.?),
47424911 });
4743
47444912 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
47454913 const dst_alias = registerAlias(dst_reg, abi_size);
47464914 switch (mir_tag[0]) {
......@@ -4799,7 +4967,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
47994967 src_mcv.getReg().?
48004968 else
48014969 try self.copyToTmpRegister(ty, src_mcv);
4802 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, mat_src_reg.to128());
4970 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, mat_src_reg.to128());
48034971 try self.asmRegisterRegisterRegister(.{ .v_ss, .sqrt }, dst_reg, dst_reg, dst_reg);
48044972 try self.asmRegisterRegisterImmediate(
48054973 .{ .v_, .cvtps2ph },
......@@ -4819,7 +4987,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
48194987 16 => if (self.hasFeature(.f16c)) switch (ty.vectorLen()) {
48204988 1 => {
48214989 try self.asmRegisterRegister(
4822 .{ .v_, .cvtph2ps },
4990 .{ .v_ps, .cvtph2 },
48234991 dst_reg,
48244992 (if (src_mcv.isRegister())
48254993 src_mcv.getReg().?
......@@ -4843,13 +5011,13 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
48435011 2...8 => {
48445012 const wide_reg = registerAlias(dst_reg, abi_size * 2);
48455013 if (src_mcv.isMemory()) try self.asmRegisterMemory(
4846 .{ .v_, .cvtph2ps },
5014 .{ .v_ps, .cvtph2 },
48475015 wide_reg,
48485016 src_mcv.mem(Memory.PtrSize.fromSize(
48495017 @intCast(u32, @divExact(wide_reg.bitSize(), 16)),
48505018 )),
48515019 ) else try self.asmRegisterRegister(
4852 .{ .v_, .cvtph2ps },
5020 .{ .v_ps, .cvtph2 },
48535021 wide_reg,
48545022 (if (src_mcv.isRegister())
48555023 src_mcv.getReg().?
......@@ -5256,64 +5424,24 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
52565424
52575425fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
52585426 const ptr_field_ty = self.air.typeOfIndex(inst);
5259 const mcv = try self.resolveInst(operand);
52605427 const ptr_container_ty = self.air.typeOf(operand);
52615428 const container_ty = ptr_container_ty.childType();
5262 const field_offset = switch (container_ty.containerLayout()) {
5263 .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, self.target.*)),
5429 const field_offset = @intCast(i32, switch (container_ty.containerLayout()) {
5430 .Auto, .Extern => container_ty.structFieldOffset(index, self.target.*),
52645431 .Packed => if (container_ty.zigTypeTag() == .Struct and
52655432 ptr_field_ty.ptrInfo().data.host_size == 0)
52665433 container_ty.packedStructFieldByteOffset(index, self.target.*)
52675434 else
52685435 0,
5269 };
5270
5271 const result: MCValue = result: {
5272 switch (mcv) {
5273 .load_frame, .lea_tlv, .load_tlv => {
5274 const offset_reg = try self.copyToTmpRegister(Type.usize, .{
5275 .immediate = field_offset,
5276 });
5277 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
5278 defer self.register_manager.unlockReg(offset_reg_lock);
5279
5280 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, Type.usize, switch (mcv) {
5281 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
5282 else => mcv,
5283 });
5284 try self.genBinOpMir(.{ ._, .add }, Type.usize, dst_mcv, .{ .register = offset_reg });
5285 break :result dst_mcv;
5286 },
5287 .indirect => |reg_off| break :result .{ .indirect = .{
5288 .reg = reg_off.reg,
5289 .off = reg_off.off + @intCast(i32, field_offset),
5290 } },
5291 .lea_frame => |frame_addr| break :result .{ .lea_frame = .{
5292 .index = frame_addr.index,
5293 .off = frame_addr.off + @intCast(i32, field_offset),
5294 } },
5295 .register, .register_offset => {
5296 const src_reg = mcv.getReg().?;
5297 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
5298 defer self.register_manager.unlockReg(src_lock);
5436 });
52995437
5300 const dst_mcv: MCValue = if (self.reuseOperand(inst, operand, 0, mcv))
5301 mcv
5302 else
5303 .{ .register = try self.copyToTmpRegister(ptr_field_ty, mcv) };
5304 break :result .{ .register_offset = .{
5305 .reg = dst_mcv.getReg().?,
5306 .off = switch (dst_mcv) {
5307 .register => 0,
5308 .register_offset => |reg_off| reg_off.off,
5309 else => unreachable,
5310 } + @intCast(i32, field_offset),
5311 } };
5312 },
5313 else => return self.fail("TODO implement fieldPtr for {}", .{mcv}),
5314 }
5315 };
5316 return result;
5438 const src_mcv = try self.resolveInst(operand);
5439 const dst_mcv = if (switch (src_mcv) {
5440 .immediate, .lea_frame => true,
5441 .register, .register_offset => self.reuseOperand(inst, operand, 0, src_mcv),
5442 else => false,
5443 }) src_mcv else try self.copyToRegisterWithInstTracking(inst, ptr_field_ty, src_mcv);
5444 return dst_mcv.offset(field_offset);
53175445}
53185446
53195447fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
......@@ -5324,8 +5452,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
53245452 const index = extra.field_index;
53255453
53265454 const container_ty = self.air.typeOf(operand);
5455 const container_rc = regClassForType(container_ty);
53275456 const field_ty = container_ty.structFieldType(index);
53285457 if (!field_ty.hasRuntimeBitsIgnoreComptime()) break :result .none;
5458 const field_rc = regClassForType(field_ty);
5459 const field_is_gp = field_rc.supersetOf(gp);
53295460
53305461 const src_mcv = try self.resolveInst(operand);
53315462 const field_off = switch (container_ty.containerLayout()) {
......@@ -5358,7 +5489,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
53585489 return self.fail("TODO implement struct_field_val with large packed field", .{});
53595490 }
53605491
5361 const dst_reg = try self.register_manager.allocReg(inst, gp);
5492 const dst_reg = try self.register_manager.allocReg(if (field_is_gp) inst else null, gp);
53625493 const field_extra_bits = self.regExtraBits(field_ty);
53635494 const load_abi_size =
53645495 if (field_bit_off < field_extra_bits) field_abi_size else field_abi_size * 2;
......@@ -5409,30 +5540,23 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
54095540 if (field_extra_bits > 0) try self.truncateRegister(field_ty, dst_reg);
54105541
54115542 const dst_mcv = MCValue{ .register = dst_reg };
5412 const dst_rc = regClassForType(field_ty);
5413 if (dst_rc.eql(gp)) break :result dst_mcv;
5414
5415 const result_reg = try self.register_manager.allocReg(inst, dst_rc);
5416 try self.genSetReg(result_reg, field_ty, dst_mcv);
5417 break :result .{ .register = result_reg };
5543 break :result if (field_is_gp)
5544 dst_mcv
5545 else
5546 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);
54185547 },
54195548 .register => |reg| {
54205549 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
54215550 defer self.register_manager.unlockReg(reg_lock);
54225551
5423 const dst_mcv = if (self.reuseOperand(inst, operand, 0, src_mcv))
5424 src_mcv
5552 const dst_reg = if (src_mcv.isRegister() and field_rc.supersetOf(container_rc) and
5553 self.reuseOperand(inst, operand, 0, src_mcv))
5554 src_mcv.getReg().?
54255555 else
5426 try self.copyToRegisterWithInstTracking(
5427 inst,
5428 Type.usize,
5429 .{ .register = reg.to64() },
5430 );
5431 const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) {
5432 .register => |a_reg| self.register_manager.lockReg(a_reg),
5433 else => null,
5434 };
5435 defer if (dst_mcv_lock) |lock| self.register_manager.unlockReg(lock);
5556 try self.copyToTmpRegister(Type.usize, .{ .register = reg.to64() });
5557 const dst_mcv = MCValue{ .register = dst_reg };
5558 const dst_lock = self.register_manager.lockReg(dst_reg);
5559 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
54365560
54375561 // Shift by struct_field_offset.
54385562 try self.genShiftBinOpMir(
......@@ -5459,7 +5583,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
54595583 registerAlias(dst_mcv.register, field_byte_size),
54605584 );
54615585 }
5462 break :result dst_mcv;
5586
5587 break :result if (field_rc.supersetOf(gp))
5588 dst_mcv
5589 else
5590 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);
54635591 },
54645592 .register_overflow => |ro| {
54655593 switch (index) {
......@@ -6339,12 +6467,13 @@ fn genBinOp(
63396467 else
63406468 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
63416469 );
6342 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, dst_reg);
6470 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
63436471 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp_reg, dst_reg);
63446472 try self.asmRegisterRegisterRegister(
63456473 switch (air_tag) {
63466474 .add => .{ .v_ss, .add },
63476475 .sub => .{ .v_ss, .sub },
6476 .mul => .{ .v_ss, .mul },
63486477 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ss, .div },
63496478 .max => .{ .v_ss, .max },
63506479 .min => .{ .v_ss, .max },
......@@ -6393,6 +6522,234 @@ fn genBinOp(
63936522 },
63946523 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
63956524 else => null,
6525 .Int => switch (lhs_ty.childType().intInfo(self.target.*).bits) {
6526 8 => switch (lhs_ty.vectorLen()) {
6527 1...16 => switch (air_tag) {
6528 .add,
6529 .addwrap,
6530 => if (self.hasFeature(.avx)) .{ .vp_b, .add } else .{ .p_b, .add },
6531 .sub,
6532 .subwrap,
6533 => if (self.hasFeature(.avx)) .{ .vp_b, .sub } else .{ .p_b, .sub },
6534 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },
6535 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },
6536 .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor },
6537 .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6538 .signed => if (self.hasFeature(.avx))
6539 .{ .vp_b, .mins }
6540 else if (self.hasFeature(.sse4_1))
6541 .{ .p_b, .mins }
6542 else
6543 null,
6544 .unsigned => if (self.hasFeature(.avx))
6545 .{ .vp_b, .minu }
6546 else if (self.hasFeature(.sse4_1))
6547 .{ .p_b, .minu }
6548 else
6549 null,
6550 },
6551 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6552 .signed => if (self.hasFeature(.avx))
6553 .{ .vp_b, .maxs }
6554 else if (self.hasFeature(.sse4_1))
6555 .{ .p_b, .maxs }
6556 else
6557 null,
6558 .unsigned => if (self.hasFeature(.avx))
6559 .{ .vp_b, .maxu }
6560 else if (self.hasFeature(.sse4_1))
6561 .{ .p_b, .maxu }
6562 else
6563 null,
6564 },
6565 else => null,
6566 },
6567 17...32 => switch (air_tag) {
6568 .add,
6569 .addwrap,
6570 => if (self.hasFeature(.avx2)) .{ .vp_b, .add } else null,
6571 .sub,
6572 .subwrap,
6573 => if (self.hasFeature(.avx2)) .{ .vp_b, .sub } else null,
6574 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,
6575 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,
6576 .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null,
6577 .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6578 .signed => if (self.hasFeature(.avx2)) .{ .vp_b, .mins } else null,
6579 .unsigned => if (self.hasFeature(.avx)) .{ .vp_b, .minu } else null,
6580 },
6581 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6582 .signed => if (self.hasFeature(.avx2)) .{ .vp_b, .maxs } else null,
6583 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_b, .maxu } else null,
6584 },
6585 else => null,
6586 },
6587 else => null,
6588 },
6589 16 => switch (lhs_ty.vectorLen()) {
6590 1...8 => switch (air_tag) {
6591 .add,
6592 .addwrap,
6593 => if (self.hasFeature(.avx)) .{ .vp_w, .add } else .{ .p_w, .add },
6594 .sub,
6595 .subwrap,
6596 => if (self.hasFeature(.avx)) .{ .vp_w, .sub } else .{ .p_w, .sub },
6597 .mul,
6598 .mulwrap,
6599 => if (self.hasFeature(.avx)) .{ .vp_w, .mull } else .{ .p_d, .mull },
6600 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },
6601 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },
6602 .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor },
6603 .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6604 .signed => if (self.hasFeature(.avx))
6605 .{ .vp_w, .mins }
6606 else
6607 .{ .p_w, .mins },
6608 .unsigned => if (self.hasFeature(.avx))
6609 .{ .vp_w, .minu }
6610 else
6611 .{ .p_w, .minu },
6612 },
6613 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6614 .signed => if (self.hasFeature(.avx))
6615 .{ .vp_w, .maxs }
6616 else
6617 .{ .p_w, .maxs },
6618 .unsigned => if (self.hasFeature(.avx))
6619 .{ .vp_w, .maxu }
6620 else
6621 .{ .p_w, .maxu },
6622 },
6623 else => null,
6624 },
6625 9...16 => switch (air_tag) {
6626 .add,
6627 .addwrap,
6628 => if (self.hasFeature(.avx2)) .{ .vp_w, .add } else null,
6629 .sub,
6630 .subwrap,
6631 => if (self.hasFeature(.avx2)) .{ .vp_w, .sub } else null,
6632 .mul,
6633 .mulwrap,
6634 => if (self.hasFeature(.avx2)) .{ .vp_w, .mull } else null,
6635 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,
6636 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,
6637 .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null,
6638 .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6639 .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .mins } else null,
6640 .unsigned => if (self.hasFeature(.avx)) .{ .vp_w, .minu } else null,
6641 },
6642 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6643 .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .maxs } else null,
6644 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_w, .maxu } else null,
6645 },
6646 else => null,
6647 },
6648 else => null,
6649 },
6650 32 => switch (lhs_ty.vectorLen()) {
6651 1...4 => switch (air_tag) {
6652 .add,
6653 .addwrap,
6654 => if (self.hasFeature(.avx)) .{ .vp_d, .add } else .{ .p_d, .add },
6655 .sub,
6656 .subwrap,
6657 => if (self.hasFeature(.avx)) .{ .vp_d, .sub } else .{ .p_d, .sub },
6658 .mul,
6659 .mulwrap,
6660 => if (self.hasFeature(.avx))
6661 .{ .vp_d, .mull }
6662 else if (self.hasFeature(.sse4_1))
6663 .{ .p_d, .mull }
6664 else
6665 null,
6666 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },
6667 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },
6668 .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor },
6669 .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6670 .signed => if (self.hasFeature(.avx))
6671 .{ .vp_d, .mins }
6672 else if (self.hasFeature(.sse4_1))
6673 .{ .p_d, .mins }
6674 else
6675 null,
6676 .unsigned => if (self.hasFeature(.avx))
6677 .{ .vp_d, .minu }
6678 else if (self.hasFeature(.sse4_1))
6679 .{ .p_d, .minu }
6680 else
6681 null,
6682 },
6683 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6684 .signed => if (self.hasFeature(.avx))
6685 .{ .vp_d, .maxs }
6686 else if (self.hasFeature(.sse4_1))
6687 .{ .p_d, .maxs }
6688 else
6689 null,
6690 .unsigned => if (self.hasFeature(.avx))
6691 .{ .vp_d, .maxu }
6692 else if (self.hasFeature(.sse4_1))
6693 .{ .p_d, .maxu }
6694 else
6695 null,
6696 },
6697 else => null,
6698 },
6699 5...8 => switch (air_tag) {
6700 .add,
6701 .addwrap,
6702 => if (self.hasFeature(.avx2)) .{ .vp_d, .add } else null,
6703 .sub,
6704 .subwrap,
6705 => if (self.hasFeature(.avx2)) .{ .vp_d, .sub } else null,
6706 .mul,
6707 .mulwrap,
6708 => if (self.hasFeature(.avx2)) .{ .vp_d, .mull } else null,
6709 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,
6710 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,
6711 .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null,
6712 .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6713 .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .mins } else null,
6714 .unsigned => if (self.hasFeature(.avx)) .{ .vp_d, .minu } else null,
6715 },
6716 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6717 .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .maxs } else null,
6718 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_d, .maxu } else null,
6719 },
6720 else => null,
6721 },
6722 else => null,
6723 },
6724 64 => switch (lhs_ty.vectorLen()) {
6725 1...2 => switch (air_tag) {
6726 .add,
6727 .addwrap,
6728 => if (self.hasFeature(.avx)) .{ .vp_q, .add } else .{ .p_q, .add },
6729 .sub,
6730 .subwrap,
6731 => if (self.hasFeature(.avx)) .{ .vp_q, .sub } else .{ .p_q, .sub },
6732 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },
6733 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },
6734 .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor },
6735 else => null,
6736 },
6737 3...4 => switch (air_tag) {
6738 .add,
6739 .addwrap,
6740 => if (self.hasFeature(.avx2)) .{ .vp_q, .add } else null,
6741 .sub,
6742 .subwrap,
6743 => if (self.hasFeature(.avx2)) .{ .vp_q, .sub } else null,
6744 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,
6745 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,
6746 .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null,
6747 else => null,
6748 },
6749 else => null,
6750 },
6751 else => null,
6752 },
63966753 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
63976754 16 => if (self.hasFeature(.f16c)) switch (lhs_ty.vectorLen()) {
63986755 1 => {
......@@ -6415,12 +6772,13 @@ fn genBinOp(
64156772 else
64166773 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
64176774 );
6418 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, dst_reg);
6775 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
64196776 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp_reg, dst_reg);
64206777 try self.asmRegisterRegisterRegister(
64216778 switch (air_tag) {
64226779 .add => .{ .v_ss, .add },
64236780 .sub => .{ .v_ss, .sub },
6781 .mul => .{ .v_ss, .mul },
64246782 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ss, .div },
64256783 .max => .{ .v_ss, .max },
64266784 .min => .{ .v_ss, .max },
......@@ -6457,7 +6815,7 @@ fn genBinOp(
64576815 else
64586816 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
64596817 );
6460 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, dst_reg);
6818 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
64616819 try self.asmRegisterRegisterRegister(
64626820 .{ .v_ps, .movhl },
64636821 tmp_reg,
......@@ -6468,6 +6826,7 @@ fn genBinOp(
64686826 switch (air_tag) {
64696827 .add => .{ .v_ps, .add },
64706828 .sub => .{ .v_ps, .sub },
6829 .mul => .{ .v_ps, .mul },
64716830 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
64726831 .max => .{ .v_ps, .max },
64736832 .min => .{ .v_ps, .max },
......@@ -6490,13 +6849,13 @@ fn genBinOp(
64906849 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
64916850 defer self.register_manager.unlockReg(tmp_lock);
64926851
6493 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, dst_reg);
6852 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
64946853 if (src_mcv.isMemory()) try self.asmRegisterMemory(
6495 .{ .v_, .cvtph2ps },
6854 .{ .v_ps, .cvtph2 },
64966855 tmp_reg,
64976856 src_mcv.mem(.qword),
64986857 ) else try self.asmRegisterRegister(
6499 .{ .v_, .cvtph2ps },
6858 .{ .v_ps, .cvtph2 },
65006859 tmp_reg,
65016860 (if (src_mcv.isRegister())
65026861 src_mcv.getReg().?
......@@ -6507,6 +6866,7 @@ fn genBinOp(
65076866 switch (air_tag) {
65086867 .add => .{ .v_ps, .add },
65096868 .sub => .{ .v_ps, .sub },
6869 .mul => .{ .v_ps, .mul },
65106870 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
65116871 .max => .{ .v_ps, .max },
65126872 .min => .{ .v_ps, .max },
......@@ -6529,13 +6889,13 @@ fn genBinOp(
65296889 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
65306890 defer self.register_manager.unlockReg(tmp_lock);
65316891
6532 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg.to256(), dst_reg);
6892 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg.to256(), dst_reg);
65336893 if (src_mcv.isMemory()) try self.asmRegisterMemory(
6534 .{ .v_, .cvtph2ps },
6894 .{ .v_ps, .cvtph2 },
65356895 tmp_reg,
65366896 src_mcv.mem(.xword),
65376897 ) else try self.asmRegisterRegister(
6538 .{ .v_, .cvtph2ps },
6898 .{ .v_ps, .cvtph2 },
65396899 tmp_reg,
65406900 (if (src_mcv.isRegister())
65416901 src_mcv.getReg().?
......@@ -6546,6 +6906,7 @@ fn genBinOp(
65466906 switch (air_tag) {
65476907 .add => .{ .v_ps, .add },
65486908 .sub => .{ .v_ps, .sub },
6909 .mul => .{ .v_ps, .mul },
65496910 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
65506911 .max => .{ .v_ps, .max },
65516912 .min => .{ .v_ps, .max },
......@@ -6681,7 +7042,7 @@ fn genBinOp(
66817042 );
66827043 }
66837044 switch (air_tag) {
6684 .add, .sub, .mul, .div_float, .div_exact => {},
7045 .add, .addwrap, .sub, .subwrap, .mul, .mulwrap, .div_float, .div_exact => {},
66857046 .div_trunc, .div_floor => try self.genRound(
66867047 lhs_ty,
66877048 dst_reg,
......@@ -6692,6 +7053,7 @@ fn genBinOp(
66927053 else => unreachable,
66937054 },
66947055 ),
7056 .bit_and, .bit_or, .xor => {},
66957057 .max, .min => {}, // TODO: unordered select
66967058 else => unreachable,
66977059 }
......@@ -6712,7 +7074,6 @@ fn genBinOpMir(
67127074 .dead,
67137075 .undef,
67147076 .immediate,
6715 .register_offset,
67167077 .eflags,
67177078 .register_overflow,
67187079 .lea_direct,
......@@ -6721,7 +7082,9 @@ fn genBinOpMir(
67217082 .lea_frame,
67227083 .reserved_frame,
67237084 => unreachable, // unmodifiable destination
6724 .register => |dst_reg| {
7085 .register, .register_offset => {
7086 assert(dst_mcv.isRegister());
7087 const dst_reg = dst_mcv.getReg().?;
67257088 const dst_alias = registerAlias(dst_reg, abi_size);
67267089 switch (src_mcv) {
67277090 .none,
......@@ -7185,13 +7548,13 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void {
71857548 switch (self.debug_output) {
71867549 .dwarf => |dw| {
71877550 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {
7188 .register => |reg| .{ .register = reg.dwarfLocOp() },
7551 .register => |reg| .{ .register = reg.dwarfNum() },
71897552 // TODO use a frame index
71907553 .load_frame => return,
71917554 //.stack_offset => |off| .{
71927555 // .stack = .{
71937556 // // TODO handle -fomit-frame-pointer
7194 // .fp_register = Register.rbp.dwarfLocOpDeref(),
7557 // .fp_register = Register.rbp.dwarfNum(),
71957558 // .offset = -off,
71967559 // },
71977560 //},
......@@ -7223,11 +7586,11 @@ fn genVarDbgInfo(
72237586 switch (self.debug_output) {
72247587 .dwarf => |dw| {
72257588 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {
7226 .register => |reg| .{ .register = reg.dwarfLocOp() },
7589 .register => |reg| .{ .register = reg.dwarfNum() },
72277590 // TODO use a frame index
72287591 .load_frame, .lea_frame => return,
72297592 //=> |off| .{ .stack = .{
7230 // .fp_register = Register.rbp.dwarfLocOpDeref(),
7593 // .fp_register = Register.rbp.dwarfNum(),
72317594 // .offset = -off,
72327595 //} },
72337596 .memory => |address| .{ .memory = address },
......@@ -7364,11 +7727,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
73647727 // on linking.
73657728 const mod = self.bin_file.options.module.?;
73667729 if (self.air.value(callee)) |func_value| {
7367 if (func_value.castTag(.function)) |func_payload| {
7368 const func = func_payload.data;
7369
7730 if (if (func_value.castTag(.function)) |func_payload|
7731 func_payload.data.owner_decl
7732 else if (func_value.castTag(.decl_ref)) |decl_ref_payload|
7733 decl_ref_payload.data
7734 else
7735 null) |owner_decl|
7736 {
73707737 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
7371 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
7738 const atom_index = try elf_file.getOrCreateAtomForDecl(owner_decl);
73727739 const atom = elf_file.getAtom(atom_index);
73737740 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
73747741 const got_addr = atom.getOffsetTableAddress(elf_file);
......@@ -7377,17 +7744,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
73777744 .disp = @intCast(i32, got_addr),
73787745 }));
73797746 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
7380 const atom = try coff_file.getOrCreateAtomForDecl(func.owner_decl);
7747 const atom = try coff_file.getOrCreateAtomForDecl(owner_decl);
73817748 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
73827749 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
73837750 try self.asmRegister(.{ ._, .call }, .rax);
73847751 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
7385 const atom = try macho_file.getOrCreateAtomForDecl(func.owner_decl);
7752 const atom = try macho_file.getOrCreateAtomForDecl(owner_decl);
73867753 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
73877754 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
73887755 try self.asmRegister(.{ ._, .call }, .rax);
73897756 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
7390 const decl_block_index = try p9.seeDecl(func.owner_decl);
7757 const decl_block_index = try p9.seeDecl(owner_decl);
73917758 const decl_block = p9.getDeclBlock(decl_block_index);
73927759 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
73937760 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
......@@ -7577,7 +7944,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
75777944 else
75787945 try self.copyToTmpRegister(ty, src_mcv)).to128(),
75797946 );
7580 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, tmp1_reg, tmp1_reg);
7947 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, tmp1_reg, tmp1_reg);
75817948 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp2_reg, tmp1_reg);
75827949 try self.genBinOpMir(.{ ._ss, .ucomi }, ty, tmp1_mcv, tmp2_mcv);
75837950 } else return self.fail("TODO implement airCmp for {}", .{
......@@ -8568,47 +8935,190 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
85688935 return self.finishAirResult(inst, result);
85698936}
85708937
8571fn movMirTag(self: *Self, ty: Type, aligned: bool) !Mir.Inst.FixedTag {
8938const MoveStrategy = union(enum) {
8939 move: Mir.Inst.FixedTag,
8940 insert_extract: InsertExtract,
8941 vex_insert_extract: InsertExtract,
8942
8943 const InsertExtract = struct {
8944 insert: Mir.Inst.FixedTag,
8945 extract: Mir.Inst.FixedTag,
8946 };
8947};
8948fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
85728949 switch (ty.zigTypeTag()) {
8573 else => return .{ ._, .mov },
8950 else => return .{ .move = .{ ._, .mov } },
85748951 .Float => switch (ty.floatBits(self.target.*)) {
8575 16 => unreachable, // needs special handling
8576 32 => return if (self.hasFeature(.avx)) .{ .v_ss, .mov } else .{ ._ss, .mov },
8577 64 => return if (self.hasFeature(.avx)) .{ .v_sd, .mov } else .{ ._sd, .mov },
8578 128 => return if (self.hasFeature(.avx))
8579 if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu }
8580 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu },
8952 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
8953 .insert = .{ .vp_w, .insr },
8954 .extract = .{ .vp_w, .extr },
8955 } } else .{ .insert_extract = .{
8956 .insert = .{ .p_w, .insr },
8957 .extract = .{ .p_w, .extr },
8958 } },
8959 32 => return .{ .move = if (self.hasFeature(.avx)) .{ .v_ss, .mov } else .{ ._ss, .mov } },
8960 64 => return .{ .move = if (self.hasFeature(.avx)) .{ .v_sd, .mov } else .{ ._sd, .mov } },
8961 128 => return .{ .move = if (self.hasFeature(.avx))
8962 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
8963 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
85818964 else => {},
85828965 },
85838966 .Vector => switch (ty.childType().zigTypeTag()) {
8967 .Int => switch (ty.childType().intInfo(self.target.*).bits) {
8968 8 => switch (ty.vectorLen()) {
8969 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
8970 .insert = .{ .vp_b, .insr },
8971 .extract = .{ .vp_b, .extr },
8972 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{
8973 .insert = .{ .p_b, .insr },
8974 .extract = .{ .p_b, .extr },
8975 } },
8976 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
8977 .insert = .{ .vp_w, .insr },
8978 .extract = .{ .vp_w, .extr },
8979 } } else .{ .insert_extract = .{
8980 .insert = .{ .p_w, .insr },
8981 .extract = .{ .p_w, .extr },
8982 } },
8983 3...4 => return .{ .move = if (self.hasFeature(.avx))
8984 .{ .v_d, .mov }
8985 else
8986 .{ ._d, .mov } },
8987 5...8 => return .{ .move = if (self.hasFeature(.avx))
8988 .{ .v_q, .mov }
8989 else
8990 .{ ._q, .mov } },
8991 9...16 => return .{ .move = if (self.hasFeature(.avx))
8992 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
8993 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
8994 17...32 => if (self.hasFeature(.avx))
8995 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
8996 else => {},
8997 },
8998 16 => switch (ty.vectorLen()) {
8999 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
9000 .insert = .{ .vp_w, .insr },
9001 .extract = .{ .vp_w, .extr },
9002 } } else .{ .insert_extract = .{
9003 .insert = .{ .p_w, .insr },
9004 .extract = .{ .p_w, .extr },
9005 } },
9006 2 => return .{ .move = if (self.hasFeature(.avx))
9007 .{ .v_d, .mov }
9008 else
9009 .{ ._d, .mov } },
9010 3...4 => return .{ .move = if (self.hasFeature(.avx))
9011 .{ .v_q, .mov }
9012 else
9013 .{ ._q, .mov } },
9014 5...8 => return .{ .move = if (self.hasFeature(.avx))
9015 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
9016 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
9017 9...16 => if (self.hasFeature(.avx))
9018 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
9019 else => {},
9020 },
9021 32 => switch (ty.vectorLen()) {
9022 1 => return .{ .move = if (self.hasFeature(.avx))
9023 .{ .v_d, .mov }
9024 else
9025 .{ ._d, .mov } },
9026 2 => return .{ .move = if (self.hasFeature(.avx))
9027 .{ .v_q, .mov }
9028 else
9029 .{ ._q, .mov } },
9030 3...4 => return .{ .move = if (self.hasFeature(.avx))
9031 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
9032 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
9033 5...8 => if (self.hasFeature(.avx))
9034 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
9035 else => {},
9036 },
9037 64 => switch (ty.vectorLen()) {
9038 1 => return .{ .move = if (self.hasFeature(.avx))
9039 .{ .v_q, .mov }
9040 else
9041 .{ ._q, .mov } },
9042 2 => return .{ .move = if (self.hasFeature(.avx))
9043 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
9044 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
9045 3...4 => if (self.hasFeature(.avx))
9046 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
9047 else => {},
9048 },
9049 128 => switch (ty.vectorLen()) {
9050 1 => return .{ .move = if (self.hasFeature(.avx))
9051 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
9052 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
9053 2 => if (self.hasFeature(.avx))
9054 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
9055 else => {},
9056 },
9057 256 => switch (ty.vectorLen()) {
9058 1 => if (self.hasFeature(.avx))
9059 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
9060 else => {},
9061 },
9062 else => {},
9063 },
85849064 .Float => switch (ty.childType().floatBits(self.target.*)) {
85859065 16 => switch (ty.vectorLen()) {
8586 1 => unreachable, // needs special handling
8587 2 => return if (self.hasFeature(.avx)) .{ .v_ss, .mov } else .{ ._ss, .mov },
8588 3...4 => return if (self.hasFeature(.avx)) .{ .v_sd, .mov } else .{ ._sd, .mov },
8589 5...8 => return if (self.hasFeature(.avx))
8590 if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu }
8591 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu },
9066 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
9067 .insert = .{ .vp_w, .insr },
9068 .extract = .{ .vp_w, .extr },
9069 } } else .{ .insert_extract = .{
9070 .insert = .{ .p_w, .insr },
9071 .extract = .{ .p_w, .extr },
9072 } },
9073 2 => return .{ .move = if (self.hasFeature(.avx))
9074 .{ .v_d, .mov }
9075 else
9076 .{ ._d, .mov } },
9077 3...4 => return .{ .move = if (self.hasFeature(.avx))
9078 .{ .v_q, .mov }
9079 else
9080 .{ ._q, .mov } },
9081 5...8 => return .{ .move = if (self.hasFeature(.avx))
9082 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
9083 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
85929084 9...16 => if (self.hasFeature(.avx))
8593 return if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu },
9085 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
85949086 else => {},
85959087 },
85969088 32 => switch (ty.vectorLen()) {
8597 1 => return if (self.hasFeature(.avx)) .{ .v_ss, .mov } else .{ ._ss, .mov },
8598 2...4 => return if (self.hasFeature(.avx))
9089 1 => return .{ .move = if (self.hasFeature(.avx))
9090 .{ .v_ss, .mov }
9091 else
9092 .{ ._ss, .mov } },
9093 2 => return .{ .move = if (self.hasFeature(.avx))
9094 .{ .v_sd, .mov }
9095 else
9096 .{ ._sd, .mov } },
9097 3...4 => return .{ .move = if (self.hasFeature(.avx))
85999098 if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu }
8600 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu },
9099 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } },
86019100 5...8 => if (self.hasFeature(.avx))
8602 return if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu },
9101 return .{ .move = if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu } },
86039102 else => {},
86049103 },
86059104 64 => switch (ty.vectorLen()) {
8606 1 => return if (self.hasFeature(.avx)) .{ .v_sd, .mov } else .{ ._sd, .mov },
8607 2 => return if (self.hasFeature(.avx))
8608 if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu }
8609 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu },
9105 1 => return .{ .move = if (self.hasFeature(.avx))
9106 .{ .v_sd, .mov }
9107 else
9108 .{ ._sd, .mov } },
9109 2 => return .{ .move = if (self.hasFeature(.avx))
9110 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
9111 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
86109112 3...4 => if (self.hasFeature(.avx))
8611 return if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu },
9113 return .{ .move = if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu } },
9114 else => {},
9115 },
9116 128 => switch (ty.vectorLen()) {
9117 1 => return .{ .move = if (self.hasFeature(.avx))
9118 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
9119 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
9120 2 => if (self.hasFeature(.avx))
9121 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
86129122 else => {},
86139123 },
86149124 else => {},
......@@ -8616,15 +9126,11 @@ fn movMirTag(self: *Self, ty: Type, aligned: bool) !Mir.Inst.FixedTag {
86169126 else => {},
86179127 },
86189128 }
8619 return self.fail("TODO movMirTag for {}", .{ty.fmt(self.bin_file.options.module.?)});
9129 return self.fail("TODO moveStrategy for {}", .{ty.fmt(self.bin_file.options.module.?)});
86209130}
86219131
86229132fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void {
8623 const src_lock = switch (src_mcv) {
8624 .register => |reg| self.register_manager.lockReg(reg),
8625 .register_overflow => |ro| self.register_manager.lockReg(ro.reg),
8626 else => null,
8627 };
9133 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
86289134 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
86299135
86309136 switch (dst_mcv) {
......@@ -8720,34 +9226,94 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
87209226 );
87219227 }
87229228 },
8723 .register => |src_reg| if (dst_reg.id() != src_reg.id()) try self.asmRegisterRegister(
8724 if ((dst_reg.class() == .floating_point) == (src_reg.class() == .floating_point))
8725 switch (ty.zigTypeTag()) {
8726 else => .{ ._, .mov },
8727 .Float, .Vector => .{ ._ps, .mova },
8728 }
8729 else switch (abi_size) {
8730 2 => return try self.asmRegisterRegisterImmediate(
8731 if (dst_reg.class() == .floating_point) .{ .p_w, .insr } else .{ .p_w, .extr },
8732 registerAlias(dst_reg, 4),
8733 registerAlias(src_reg, 4),
8734 Immediate.u(0),
9229 .register => |src_reg| if (dst_reg.id() != src_reg.id()) switch (dst_reg.class()) {
9230 .general_purpose => switch (src_reg.class()) {
9231 .general_purpose => try self.asmRegisterRegister(
9232 .{ ._, .mov },
9233 registerAlias(dst_reg, abi_size),
9234 registerAlias(src_reg, abi_size),
87359235 ),
8736 4 => .{ ._d, .mov },
8737 8 => .{ ._q, .mov },
8738 else => return self.fail(
8739 "unsupported register copy from {s} to {s}",
8740 .{ @tagName(src_reg), @tagName(dst_reg) },
9236 .segment => try self.asmRegisterRegister(
9237 .{ ._, .mov },
9238 registerAlias(dst_reg, abi_size),
9239 src_reg,
87419240 ),
9241 .sse => try self.asmRegisterRegister(
9242 switch (abi_size) {
9243 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
9244 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },
9245 else => unreachable,
9246 },
9247 registerAlias(dst_reg, @max(abi_size, 4)),
9248 src_reg.to128(),
9249 ),
9250 .x87, .mmx => unreachable,
87429251 },
8743 registerAlias(dst_reg, abi_size),
8744 registerAlias(src_reg, abi_size),
8745 ),
9252 .segment => try self.asmRegisterRegister(
9253 .{ ._, .mov },
9254 dst_reg,
9255 switch (src_reg.class()) {
9256 .general_purpose, .segment => registerAlias(src_reg, abi_size),
9257 .sse => try self.copyToTmpRegister(ty, src_mcv),
9258 .x87, .mmx => unreachable,
9259 },
9260 ),
9261 .sse => switch (src_reg.class()) {
9262 .general_purpose => try self.asmRegisterRegister(
9263 switch (abi_size) {
9264 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
9265 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },
9266 else => unreachable,
9267 },
9268 dst_reg.to128(),
9269 registerAlias(src_reg, @max(abi_size, 4)),
9270 ),
9271 .segment => try self.genSetReg(
9272 dst_reg,
9273 ty,
9274 .{ .register = try self.copyToTmpRegister(ty, src_mcv) },
9275 ),
9276 .sse => try self.asmRegisterRegister(
9277 if (@as(?Mir.Inst.FixedTag, switch (ty.scalarType().zigTypeTag()) {
9278 else => switch (abi_size) {
9279 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
9280 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },
9281 9...16 => if (self.hasFeature(.avx)) .{ .v_, .movdqa } else .{ ._, .movdqa },
9282 17...32 => if (self.hasFeature(.avx)) .{ .v_, .movdqa } else null,
9283 else => null,
9284 },
9285 .Float => switch (ty.floatBits(self.target.*)) {
9286 16, 128 => switch (abi_size) {
9287 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 },
9289 9...16 => if (self.hasFeature(.avx))
9290 .{ .v_, .movdqa }
9291 else
9292 .{ ._, .movdqa },
9293 17...32 => if (self.hasFeature(.avx)) .{ .v_, .movdqa } else null,
9294 else => null,
9295 },
9296 32 => if (self.hasFeature(.avx)) .{ .v_ps, .mova } else .{ ._ps, .mova },
9297 64 => if (self.hasFeature(.avx)) .{ .v_pd, .mova } else .{ ._pd, .mova },
9298 80 => null,
9299 else => unreachable,
9300 },
9301 })) |tag| tag else return self.fail("TODO implement genSetReg for {}", .{
9302 ty.fmt(self.bin_file.options.module.?),
9303 }),
9304 registerAlias(dst_reg, abi_size),
9305 registerAlias(src_reg, abi_size),
9306 ),
9307 .x87, .mmx => unreachable,
9308 },
9309 .x87, .mmx => unreachable,
9310 },
87469311 .register_offset,
87479312 .indirect,
87489313 .load_frame,
87499314 .lea_frame,
87509315 => {
9316 const dst_alias = registerAlias(dst_reg, abi_size);
87519317 const src_mem = Memory.sib(Memory.PtrSize.fromSize(abi_size), switch (src_mcv) {
87529318 .register_offset, .indirect => |reg_off| .{
87539319 .base = .{ .reg = reg_off.reg },
......@@ -8759,71 +9325,81 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
87599325 },
87609326 else => unreachable,
87619327 });
8762 if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16)
8763 try self.asmRegisterMemoryImmediate(
8764 .{ .p_w, .insr },
8765 registerAlias(dst_reg, abi_size),
9328 switch (@as(MoveStrategy, switch (src_mcv) {
9329 .register_offset => |reg_off| switch (reg_off.off) {
9330 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }),
9331 else => .{ .move = .{ ._, .lea } },
9332 },
9333 .indirect => try self.moveStrategy(ty, false),
9334 .load_frame => |frame_addr| try self.moveStrategy(
9335 ty,
9336 self.getFrameAddrAlignment(frame_addr) >= ty.abiAlignment(self.target.*),
9337 ),
9338 .lea_frame => .{ .move = .{ ._, .lea } },
9339 else => unreachable,
9340 })) {
9341 .move => |tag| try self.asmRegisterMemory(tag, dst_alias, src_mem),
9342 .insert_extract => |ie| try self.asmRegisterMemoryImmediate(
9343 ie.insert,
9344 dst_alias,
87669345 src_mem,
87679346 Immediate.u(0),
8768 )
8769 else
8770 try self.asmRegisterMemory(
8771 switch (src_mcv) {
8772 .register_offset => |reg_off| switch (reg_off.off) {
8773 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }),
8774 else => .{ ._, .lea },
8775 },
8776 .indirect => try self.movMirTag(ty, false),
8777 .load_frame => |frame_addr| try self.movMirTag(
8778 ty,
8779 self.getFrameAddrAlignment(frame_addr) >= ty.abiAlignment(self.target.*),
8780 ),
8781 .lea_frame => .{ ._, .lea },
8782 else => unreachable,
8783 },
8784 registerAlias(dst_reg, abi_size),
9347 ),
9348 .vex_insert_extract => |ie| try self.asmRegisterRegisterMemoryImmediate(
9349 ie.insert,
9350 dst_alias,
9351 dst_alias,
87859352 src_mem,
8786 );
9353 Immediate.u(0),
9354 ),
9355 }
87879356 },
87889357 .memory, .load_direct, .load_got, .load_tlv => {
87899358 switch (src_mcv) {
87909359 .memory => |addr| if (math.cast(i32, @bitCast(i64, addr))) |small_addr| {
9360 const dst_alias = registerAlias(dst_reg, abi_size);
87919361 const src_mem = Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
87929362 .base = .{ .reg = .ds },
87939363 .disp = small_addr,
87949364 });
8795 return if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16)
8796 self.asmRegisterMemoryImmediate(
8797 .{ .p_w, .insr },
8798 registerAlias(dst_reg, abi_size),
9365 switch (try self.moveStrategy(ty, mem.isAlignedGeneric(
9366 u32,
9367 @bitCast(u32, small_addr),
9368 ty.abiAlignment(self.target.*),
9369 ))) {
9370 .move => |tag| try self.asmRegisterMemory(tag, dst_alias, src_mem),
9371 .insert_extract => |ie| try self.asmRegisterMemoryImmediate(
9372 ie.insert,
9373 dst_alias,
87999374 src_mem,
88009375 Immediate.u(0),
8801 )
8802 else
8803 self.asmRegisterMemory(
8804 try self.movMirTag(ty, mem.isAlignedGeneric(
8805 u32,
8806 @bitCast(u32, small_addr),
8807 ty.abiAlignment(self.target.*),
8808 )),
8809 registerAlias(dst_reg, abi_size),
9376 ),
9377 .vex_insert_extract => |ie| try self.asmRegisterRegisterMemoryImmediate(
9378 ie.insert,
9379 dst_alias,
9380 dst_alias,
88109381 src_mem,
8811 );
9382 Immediate.u(0),
9383 ),
9384 }
88129385 },
8813 .load_direct => |sym_index| if (!ty.isRuntimeFloat()) {
8814 const atom_index = try self.owner.getSymbolIndex(self);
8815 _ = try self.addInst(.{
8816 .tag = .mov,
8817 .ops = .direct_reloc,
8818 .data = .{ .rx = .{
8819 .r1 = dst_reg.to64(),
8820 .payload = try self.addExtra(Mir.Reloc{
8821 .atom_index = atom_index,
8822 .sym_index = sym_index,
8823 }),
8824 } },
8825 });
8826 return;
9386 .load_direct => |sym_index| switch (ty.zigTypeTag()) {
9387 else => {
9388 const atom_index = try self.owner.getSymbolIndex(self);
9389 _ = try self.addInst(.{
9390 .tag = .mov,
9391 .ops = .direct_reloc,
9392 .data = .{ .rx = .{
9393 .r1 = dst_reg.to64(),
9394 .payload = try self.addExtra(Mir.Reloc{
9395 .atom_index = atom_index,
9396 .sym_index = sym_index,
9397 }),
9398 } },
9399 });
9400 return;
9401 },
9402 .Float, .Vector => {},
88279403 },
88289404 .load_got, .load_tlv => {},
88299405 else => unreachable,
......@@ -8833,22 +9409,26 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
88339409 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
88349410 defer self.register_manager.unlockReg(addr_lock);
88359411
9412 const dst_alias = registerAlias(dst_reg, abi_size);
88369413 const src_mem = Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
88379414 .base = .{ .reg = addr_reg },
88389415 });
8839 if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16)
8840 try self.asmRegisterMemoryImmediate(
8841 .{ .p_w, .insr },
8842 registerAlias(dst_reg, abi_size),
9416 switch (try self.moveStrategy(ty, false)) {
9417 .move => |tag| try self.asmRegisterMemory(tag, dst_alias, src_mem),
9418 .insert_extract => |ie| try self.asmRegisterMemoryImmediate(
9419 ie.insert,
9420 dst_alias,
88439421 src_mem,
88449422 Immediate.u(0),
8845 )
8846 else
8847 try self.asmRegisterMemory(
8848 try self.movMirTag(ty, false),
8849 registerAlias(dst_reg, abi_size),
9423 ),
9424 .vex_insert_extract => |ie| try self.asmRegisterRegisterMemoryImmediate(
9425 ie.insert,
9426 dst_alias,
9427 dst_alias,
88509428 src_mem,
8851 );
9429 Immediate.u(0),
9430 ),
9431 }
88529432 },
88539433 .lea_direct, .lea_got => |sym_index| {
88549434 const atom_index = try self.owner.getSymbolIndex(self);
......@@ -8950,36 +9530,33 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
89509530 Memory.PtrSize.fromSize(abi_size),
89519531 .{ .base = base, .disp = disp },
89529532 );
8953 if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16)
8954 try self.asmMemoryRegisterImmediate(
8955 .{ .p_w, .extr },
9533 const src_alias = registerAlias(src_reg, abi_size);
9534 switch (try self.moveStrategy(ty, switch (base) {
9535 .none => mem.isAlignedGeneric(
9536 u32,
9537 @bitCast(u32, disp),
9538 ty.abiAlignment(self.target.*),
9539 ),
9540 .reg => |reg| switch (reg) {
9541 .es, .cs, .ss, .ds => mem.isAlignedGeneric(
9542 u32,
9543 @bitCast(u32, disp),
9544 ty.abiAlignment(self.target.*),
9545 ),
9546 else => false,
9547 },
9548 .frame => |frame_index| self.getFrameAddrAlignment(
9549 .{ .index = frame_index, .off = disp },
9550 ) >= ty.abiAlignment(self.target.*),
9551 })) {
9552 .move => |tag| try self.asmMemoryRegister(tag, dst_mem, src_alias),
9553 .insert_extract, .vex_insert_extract => |ie| try self.asmMemoryRegisterImmediate(
9554 ie.extract,
89569555 dst_mem,
8957 src_reg.to128(),
9556 src_alias,
89589557 Immediate.u(0),
8959 )
8960 else
8961 try self.asmMemoryRegister(
8962 try self.movMirTag(ty, switch (base) {
8963 .none => mem.isAlignedGeneric(
8964 u32,
8965 @bitCast(u32, disp),
8966 ty.abiAlignment(self.target.*),
8967 ),
8968 .reg => |reg| switch (reg) {
8969 .es, .cs, .ss, .ds => mem.isAlignedGeneric(
8970 u32,
8971 @bitCast(u32, disp),
8972 ty.abiAlignment(self.target.*),
8973 ),
8974 else => false,
8975 },
8976 .frame => |frame_index| self.getFrameAddrAlignment(
8977 .{ .index = frame_index, .off = disp },
8978 ) >= ty.abiAlignment(self.target.*),
8979 }),
8980 dst_mem,
8981 registerAlias(src_reg, abi_size),
8982 );
9558 ),
9559 }
89839560 },
89849561 .register_overflow => |ro| {
89859562 try self.genSetMem(
......@@ -9069,7 +9646,7 @@ fn genInlineMemcpyRegisterRegister(
90699646 try self.asmMemoryRegister(
90709647 switch (src_reg.class()) {
90719648 .general_purpose, .segment => .{ ._, .mov },
9072 .floating_point => .{ ._ss, .mov },
9649 .sse => .{ ._ss, .mov },
90739650 },
90749651 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = dst_reg, .disp = -offset }),
90759652 registerAlias(src_reg, abi_size),
......@@ -9235,10 +9812,10 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
92359812 });
92369813
92379814 const src_mcv = try self.resolveInst(ty_op.operand);
9238 const src_reg = switch (src_mcv) {
9239 .register => |reg| reg,
9240 else => try self.copyToTmpRegister(src_ty, src_mcv),
9241 };
9815 const src_reg = if (src_mcv.isRegister())
9816 src_mcv.getReg().?
9817 else
9818 try self.copyToTmpRegister(src_ty, src_mcv);
92429819 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
92439820 defer self.register_manager.unlockReg(src_lock);
92449821
......@@ -9249,23 +9826,23 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
92499826 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
92509827 defer self.register_manager.unlockReg(dst_lock);
92519828
9252 try self.asmRegisterRegister(switch (dst_ty.floatBits(self.target.*)) {
9253 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse))
9254 .{ ._, .cvtsi2ss }
9255 else
9256 return self.fail("TODO implement airIntToFloat from {} to {} without sse", .{
9257 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
9258 }),
9259 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2))
9260 .{ ._, .cvtsi2sd }
9261 else
9262 return self.fail("TODO implement airIntToFloat from {} to {} without sse2", .{
9263 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
9264 }),
9265 else => return self.fail("TODO implement airIntToFloat from {} to {}", .{
9266 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
9267 }),
9268 }, dst_reg.to128(), registerAlias(src_reg, src_size));
9829 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_ty.zigTypeTag()) {
9830 .Float => switch (dst_ty.floatBits(self.target.*)) {
9831 32 => if (self.hasFeature(.avx)) .{ .v_ss, .cvtsi2 } else .{ ._ss, .cvtsi2 },
9832 64 => if (self.hasFeature(.avx)) .{ .v_sd, .cvtsi2 } else .{ ._sd, .cvtsi2 },
9833 16, 80, 128 => null,
9834 else => unreachable,
9835 },
9836 else => null,
9837 })) |tag| tag else return self.fail("TODO implement airIntToFloat from {} to {}", .{
9838 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
9839 });
9840 const dst_alias = dst_reg.to128();
9841 const src_alias = registerAlias(src_reg, src_size);
9842 switch (mir_tag[0]) {
9843 .v_ss, .v_sd => try self.asmRegisterRegisterRegister(mir_tag, dst_alias, dst_alias, src_alias),
9844 else => try self.asmRegisterRegister(mir_tag, dst_alias, src_alias),
9845 }
92699846
92709847 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
92719848}
......@@ -9275,46 +9852,50 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
92759852
92769853 const src_ty = self.air.typeOf(ty_op.operand);
92779854 const dst_ty = self.air.typeOfIndex(inst);
9278 const operand = try self.resolveInst(ty_op.operand);
9279 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));
9280 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
9855 const dst_bits = @intCast(u32, dst_ty.bitSize(self.target.*));
9856 const dst_signedness =
9857 if (dst_ty.isAbiInt()) dst_ty.intInfo(self.target.*).signedness else .unsigned;
92819858
9282 switch (src_abi_size) {
9283 4, 8 => {},
9284 else => |size| return self.fail("TODO load ST(0) with abiSize={}", .{size}),
9285 }
9286 if (dst_abi_size > 8) {
9287 return self.fail("TODO convert float with abiSize={}", .{dst_abi_size});
9288 }
9859 const dst_size = std.math.divCeil(u32, @max(switch (dst_signedness) {
9860 .signed => dst_bits,
9861 .unsigned => dst_bits + 1,
9862 }, 32), 8) catch unreachable;
9863 if (dst_size > 8) return self.fail("TODO implement airFloatToInt from {} to {}", .{
9864 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
9865 });
92899866
9290 // move float src to ST(0)
9291 const frame_addr: FrameAddr = switch (operand) {
9292 .load_frame => |frame_addr| frame_addr,
9293 else => frame_addr: {
9294 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(src_ty, self.target.*));
9295 try self.genSetMem(.{ .frame = frame_index }, 0, src_ty, operand);
9296 break :frame_addr .{ .index = frame_index };
9297 },
9298 };
9299 try self.asmMemory(
9300 .{ .f_, .ld },
9301 Memory.sib(Memory.PtrSize.fromSize(src_abi_size), .{
9302 .base = .{ .frame = frame_addr.index },
9303 .disp = frame_addr.off,
9304 }),
9305 );
9867 const src_mcv = try self.resolveInst(ty_op.operand);
9868 const src_reg = if (src_mcv.isRegister())
9869 src_mcv.getReg().?
9870 else
9871 try self.copyToTmpRegister(src_ty, src_mcv);
9872 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
9873 defer self.register_manager.unlockReg(src_lock);
9874
9875 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty));
9876 const dst_mcv = MCValue{ .register = dst_reg };
9877 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
9878 defer self.register_manager.unlockReg(dst_lock);
93069879
9307 // convert
9308 const stack_dst = try self.allocRegOrMem(inst, false);
9309 try self.asmMemory(
9310 .{ .f_p, .istt },
9311 Memory.sib(Memory.PtrSize.fromSize(dst_abi_size), .{
9312 .base = .{ .frame = stack_dst.load_frame.index },
9313 .disp = stack_dst.load_frame.off,
9880 try self.asmRegisterRegister(
9881 if (@as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag()) {
9882 .Float => switch (src_ty.floatBits(self.target.*)) {
9883 32 => if (self.hasFeature(.avx)) .{ .v_, .cvttss2si } else .{ ._, .cvttss2si },
9884 64 => if (self.hasFeature(.avx)) .{ .v_, .cvttsd2si } else .{ ._, .cvttsd2si },
9885 16, 80, 128 => null,
9886 else => unreachable,
9887 },
9888 else => null,
9889 })) |tag| tag else return self.fail("TODO implement airFloatToInt from {} to {}", .{
9890 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
93149891 }),
9892 registerAlias(dst_reg, dst_size),
9893 src_reg.to128(),
93159894 );
93169895
9317 return self.finishAir(inst, stack_dst, .{ ty_op.operand, .none, .none });
9896 if (dst_bits < dst_size * 8) try self.truncateRegister(dst_ty, dst_reg);
9897
9898 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
93189899}
93199900
93209901fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
......@@ -9977,9 +10558,200 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
997710558
997810559fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
997910560 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
9980 _ = ty_op;
9981 return self.fail("TODO implement airSplat for x86_64", .{});
9982 //return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
10561 const vector_ty = self.air.typeOfIndex(inst);
10562 const dst_rc = regClassForType(vector_ty);
10563 const scalar_ty = vector_ty.scalarType();
10564
10565 const src_mcv = try self.resolveInst(ty_op.operand);
10566 const result: MCValue = result: {
10567 switch (scalar_ty.zigTypeTag()) {
10568 else => {},
10569 .Float => switch (scalar_ty.floatBits(self.target.*)) {
10570 32 => switch (vector_ty.vectorLen()) {
10571 1 => {
10572 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
10573 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
10574 try self.genSetReg(dst_reg, scalar_ty, src_mcv);
10575 break :result .{ .register = dst_reg };
10576 },
10577 2...4 => {
10578 if (self.hasFeature(.avx)) {
10579 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
10580 if (src_mcv.isMemory()) try self.asmRegisterMemory(
10581 .{ .v_ss, .broadcast },
10582 dst_reg.to128(),
10583 src_mcv.mem(.dword),
10584 ) else {
10585 const src_reg = if (src_mcv.isRegister())
10586 src_mcv.getReg().?
10587 else
10588 try self.copyToTmpRegister(scalar_ty, src_mcv);
10589 try self.asmRegisterRegisterRegisterImmediate(
10590 .{ .v_ps, .shuf },
10591 dst_reg.to128(),
10592 src_reg.to128(),
10593 src_reg.to128(),
10594 Immediate.u(0),
10595 );
10596 }
10597 break :result .{ .register = dst_reg };
10598 } else {
10599 const dst_mcv = if (src_mcv.isRegister() and
10600 self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
10601 src_mcv
10602 else
10603 try self.copyToRegisterWithInstTracking(inst, scalar_ty, src_mcv);
10604 const dst_reg = dst_mcv.getReg().?;
10605 try self.asmRegisterRegisterImmediate(
10606 .{ ._ps, .shuf },
10607 dst_reg.to128(),
10608 dst_reg.to128(),
10609 Immediate.u(0),
10610 );
10611 break :result dst_mcv;
10612 }
10613 },
10614 5...8 => if (self.hasFeature(.avx)) {
10615 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
10616 if (src_mcv.isMemory()) try self.asmRegisterMemory(
10617 .{ .v_ss, .broadcast },
10618 dst_reg.to256(),
10619 src_mcv.mem(.dword),
10620 ) else {
10621 const src_reg = if (src_mcv.isRegister())
10622 src_mcv.getReg().?
10623 else
10624 try self.copyToTmpRegister(scalar_ty, src_mcv);
10625 if (self.hasFeature(.avx2)) try self.asmRegisterRegister(
10626 .{ .v_ss, .broadcast },
10627 dst_reg.to256(),
10628 src_reg.to128(),
10629 ) else {
10630 try self.asmRegisterRegisterRegisterImmediate(
10631 .{ .v_ps, .shuf },
10632 dst_reg.to128(),
10633 src_reg.to128(),
10634 src_reg.to128(),
10635 Immediate.u(0),
10636 );
10637 try self.asmRegisterRegisterRegisterImmediate(
10638 .{ .v_f128, .insert },
10639 dst_reg.to256(),
10640 dst_reg.to256(),
10641 dst_reg.to128(),
10642 Immediate.u(1),
10643 );
10644 }
10645 }
10646 break :result .{ .register = dst_reg };
10647 },
10648 else => {},
10649 },
10650 64 => switch (vector_ty.vectorLen()) {
10651 1 => {
10652 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
10653 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
10654 try self.genSetReg(dst_reg, scalar_ty, src_mcv);
10655 break :result .{ .register = dst_reg };
10656 },
10657 2 => {
10658 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
10659 if (self.hasFeature(.sse3)) {
10660 if (src_mcv.isMemory()) try self.asmRegisterMemory(
10661 if (self.hasFeature(.avx)) .{ .v_, .movddup } else .{ ._, .movddup },
10662 dst_reg.to128(),
10663 src_mcv.mem(.qword),
10664 ) else try self.asmRegisterRegister(
10665 if (self.hasFeature(.avx)) .{ .v_, .movddup } else .{ ._, .movddup },
10666 dst_reg.to128(),
10667 (if (src_mcv.isRegister())
10668 src_mcv.getReg().?
10669 else
10670 try self.copyToTmpRegister(scalar_ty, src_mcv)).to128(),
10671 );
10672 break :result .{ .register = dst_reg };
10673 } else try self.asmRegisterRegister(
10674 .{ ._ps, .movlh },
10675 dst_reg.to128(),
10676 (if (src_mcv.isRegister())
10677 src_mcv.getReg().?
10678 else
10679 try self.copyToTmpRegister(scalar_ty, src_mcv)).to128(),
10680 );
10681 },
10682 3...4 => if (self.hasFeature(.avx)) {
10683 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
10684 if (src_mcv.isMemory()) try self.asmRegisterMemory(
10685 .{ .v_sd, .broadcast },
10686 dst_reg.to256(),
10687 src_mcv.mem(.qword),
10688 ) else {
10689 const src_reg = if (src_mcv.isRegister())
10690 src_mcv.getReg().?
10691 else
10692 try self.copyToTmpRegister(scalar_ty, src_mcv);
10693 if (self.hasFeature(.avx2)) try self.asmRegisterRegister(
10694 .{ .v_sd, .broadcast },
10695 dst_reg.to256(),
10696 src_reg.to128(),
10697 ) else {
10698 try self.asmRegisterRegister(
10699 .{ .v_, .movddup },
10700 dst_reg.to128(),
10701 src_reg.to128(),
10702 );
10703 try self.asmRegisterRegisterRegisterImmediate(
10704 .{ .v_f128, .insert },
10705 dst_reg.to256(),
10706 dst_reg.to256(),
10707 dst_reg.to128(),
10708 Immediate.u(1),
10709 );
10710 }
10711 }
10712 break :result .{ .register = dst_reg };
10713 },
10714 else => {},
10715 },
10716 128 => switch (vector_ty.vectorLen()) {
10717 1 => {
10718 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
10719 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
10720 try self.genSetReg(dst_reg, scalar_ty, src_mcv);
10721 break :result .{ .register = dst_reg };
10722 },
10723 2 => if (self.hasFeature(.avx)) {
10724 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
10725 if (src_mcv.isMemory()) try self.asmRegisterMemory(
10726 .{ .v_f128, .broadcast },
10727 dst_reg.to256(),
10728 src_mcv.mem(.xword),
10729 ) else {
10730 const src_reg = if (src_mcv.isRegister())
10731 src_mcv.getReg().?
10732 else
10733 try self.copyToTmpRegister(scalar_ty, src_mcv);
10734 try self.asmRegisterRegisterRegisterImmediate(
10735 .{ .v_f128, .insert },
10736 dst_reg.to256(),
10737 src_reg.to256(),
10738 src_reg.to128(),
10739 Immediate.u(1),
10740 );
10741 }
10742 break :result .{ .register = dst_reg };
10743 },
10744 else => {},
10745 },
10746 16, 80 => {},
10747 else => unreachable,
10748 },
10749 }
10750 return self.fail("TODO implement airSplat for {}", .{
10751 vector_ty.fmt(self.bin_file.options.module.?),
10752 });
10753 };
10754 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
998310755}
998410756
998510757fn airSelect(self: *Self, inst: Air.Inst.Index) !void {
......@@ -10142,9 +10914,46 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1014210914fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
1014310915 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1014410916 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
10145 _ = extra;
10146 return self.fail("TODO implement airUnionInit for x86_64", .{});
10147 //return self.finishAir(inst, result, .{ extra.init, .none, .none });
10917 const result: MCValue = result: {
10918 const union_ty = self.air.typeOfIndex(inst);
10919 const layout = union_ty.unionGetLayout(self.target.*);
10920
10921 const src_ty = self.air.typeOf(extra.init);
10922 const src_mcv = try self.resolveInst(extra.init);
10923 if (layout.tag_size == 0) {
10924 if (self.reuseOperand(inst, extra.init, 0, src_mcv)) break :result src_mcv;
10925
10926 const dst_mcv = try self.allocRegOrMem(inst, true);
10927 try self.genCopy(union_ty, dst_mcv, src_mcv);
10928 break :result dst_mcv;
10929 }
10930
10931 const dst_mcv = try self.allocRegOrMem(inst, false);
10932
10933 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
10934 const field_name = union_obj.fields.keys()[extra.field_index];
10935 const tag_ty = union_ty.unionTagTypeSafety().?;
10936 const field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?);
10937 var tag_pl = Value.Payload.U32{ .base = .{ .tag = .enum_field_index }, .data = field_index };
10938 const tag_val = Value.initPayload(&tag_pl.base);
10939 var tag_int_pl: Value.Payload.U64 = undefined;
10940 const tag_int_val = tag_val.enumToInt(tag_ty, &tag_int_pl);
10941 const tag_int = tag_int_val.toUnsignedInt(self.target.*);
10942 const tag_off = if (layout.tag_align < layout.payload_align)
10943 @intCast(i32, layout.payload_size)
10944 else
10945 0;
10946 try self.genCopy(tag_ty, dst_mcv.address().offset(tag_off).deref(), .{ .immediate = tag_int });
10947
10948 const pl_off = if (layout.tag_align < layout.payload_align)
10949 0
10950 else
10951 @intCast(i32, layout.tag_size);
10952 try self.genCopy(src_ty, dst_mcv.address().offset(pl_off).deref(), src_mcv);
10953
10954 break :result dst_mcv;
10955 };
10956 return self.finishAir(inst, result, .{ extra.init, .none, .none });
1014810957}
1014910958
1015010959fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
......@@ -10616,13 +11425,21 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
1061611425 reg.to64()
1061711426 else
1061811427 unreachable,
10619 .floating_point => if (size_bytes <= 16)
11428 .segment => if (size_bytes <= 2)
11429 reg
11430 else
11431 unreachable,
11432 .x87 => unreachable,
11433 .mmx => if (size_bytes <= 8)
11434 reg
11435 else
11436 unreachable,
11437 .sse => if (size_bytes <= 16)
1062011438 reg.to128()
1062111439 else if (size_bytes <= 32)
1062211440 reg.to256()
1062311441 else
1062411442 unreachable,
10625 .segment => unreachable,
1062611443 };
1062711444}
1062811445
src/arch/x86_64/Encoding.zig+127-75
......@@ -233,7 +233,6 @@ pub const Mnemonic = enum {
233233 cmpxchg, cmpxchg8b, cmpxchg16b,
234234 cqo, cwd, cwde,
235235 div,
236 fisttp, fld,
237236 idiv, imul, int3,
238237 ja, jae, jb, jbe, jc, jrcxz, je, jg, jge, jl, jle, jna, jnae, jnb, jnbe,
239238 jnc, jne, jng, jnge, jnl, jnle, jno, jnp, jns, jnz, jo, jp, jpe, jpo, js, jz,
......@@ -259,21 +258,30 @@ pub const Mnemonic = enum {
259258 @"test", tzcnt,
260259 ud2,
261260 xadd, xchg, xor,
261 // X87
262 fisttp, fld,
262263 // MMX
263 movd,
264 movd, movq,
265 paddb, paddd, paddq, paddsb, paddsw, paddusb, paddusw, paddw,
266 pand, pandn, por, pxor,
267 pmulhw, pmullw,
268 psubb, psubd, psubq, psubsb, psubsw, psubusb, psubusw, psubw,
264269 // SSE
265270 addps, addss,
266271 andps,
267272 andnps,
268273 cmpss,
269 cvtsi2ss,
274 cvtpi2ps, cvtps2pi, cvtsi2ss, cvtss2si, cvttps2pi, cvttss2si,
270275 divps, divss,
271276 maxps, maxss,
272277 minps, minss,
273 movaps, movhlps, movss, movups,
278 movaps, movhlps, movlhps,
279 movss, movups,
274280 mulps, mulss,
275281 orps,
276282 pextrw, pinsrw,
283 pmaxsw, pmaxub, pminsw, pminub,
284 shufps,
277285 sqrtps, sqrtss,
278286 subps, subss,
279287 ucomiss,
......@@ -283,12 +291,15 @@ pub const Mnemonic = enum {
283291 andpd,
284292 andnpd,
285293 //cmpsd,
286 cvtsd2ss, cvtsi2sd, cvtss2sd,
294 cvtdq2pd, cvtdq2ps, cvtpd2dq, cvtpd2pi, cvtpd2ps, cvtpi2pd,
295 cvtps2dq, cvtps2pd, cvtsd2si, cvtsd2ss, cvtsi2sd, cvtss2sd,
296 cvttpd2dq, cvttpd2pi, cvttps2dq, cvttsd2si,
287297 divpd, divsd,
288298 maxpd, maxsd,
289299 minpd, minsd,
290300 movapd,
291 movq, //movd, movsd,
301 movdqa, movdqu,
302 //movsd,
292303 movupd,
293304 mulpd, mulsd,
294305 orpd,
......@@ -296,6 +307,7 @@ pub const Mnemonic = enum {
296307 psrld, psrlq, psrlw,
297308 punpckhbw, punpckhdq, punpckhqdq, punpckhwd,
298309 punpcklbw, punpckldq, punpcklqdq, punpcklwd,
310 shufpd,
299311 sqrtpd, sqrtsd,
300312 subpd, subsd,
301313 ucomisd,
......@@ -303,31 +315,57 @@ pub const Mnemonic = enum {
303315 // SSE3
304316 movddup, movshdup, movsldup,
305317 // SSE4.1
318 extractps,
319 insertps,
306320 pextrb, pextrd, pextrq,
307321 pinsrb, pinsrd, pinsrq,
322 pmaxsb, pmaxsd, pmaxud, pmaxuw, pminsb, pminsd, pminud, pminuw,
323 pmulld,
308324 roundpd, roundps, roundsd, roundss,
309325 // AVX
310326 vaddpd, vaddps, vaddsd, vaddss,
311 vcvtsd2ss, vcvtsi2sd, vcvtsi2ss, vcvtss2sd,
327 vandnpd, vandnps, vandpd, vandps,
328 vbroadcastf128, vbroadcastsd, vbroadcastss,
329 vcvtdq2pd, vcvtdq2ps, vcvtpd2dq, vcvtpd2ps,
330 vcvtps2dq, vcvtps2pd, vcvtsd2si, vcvtsd2ss,
331 vcvtsi2sd, vcvtsi2ss, vcvtss2sd, vcvtss2si,
332 vcvttpd2dq, vcvttps2dq, vcvttsd2si, vcvttss2si,
312333 vdivpd, vdivps, vdivsd, vdivss,
334 vextractf128, vextractps,
335 vinsertf128, vinsertps,
313336 vmaxpd, vmaxps, vmaxsd, vmaxss,
314337 vminpd, vminps, vminsd, vminss,
315338 vmovapd, vmovaps,
316 vmovddup, vmovhlps,
339 vmovd,
340 vmovddup,
341 vmovdqa, vmovdqu,
342 vmovhlps, vmovlhps,
343 vmovq,
317344 vmovsd,
318345 vmovshdup, vmovsldup,
319346 vmovss,
320347 vmovupd, vmovups,
321348 vmulpd, vmulps, vmulsd, vmulss,
349 vorpd, vorps,
350 vpaddb, vpaddd, vpaddq, vpaddsb, vpaddsw, vpaddusb, vpaddusw, vpaddw,
351 vpand, vpandn,
322352 vpextrb, vpextrd, vpextrq, vpextrw,
323353 vpinsrb, vpinsrd, vpinsrq, vpinsrw,
354 vpmaxsb, vpmaxsd, vpmaxsw, vpmaxub, vpmaxud, vpmaxuw,
355 vpminsb, vpminsd, vpminsw, vpminub, vpminud, vpminuw,
356 vpmulhw, vpmulld, vpmullw,
357 vpor,
324358 vpshufhw, vpshuflw,
325359 vpsrld, vpsrlq, vpsrlw,
360 vpsubb, vpsubd, vpsubq, vpsubsb, vpsubsw, vpsubusb, vpsubusw, vpsubw,
326361 vpunpckhbw, vpunpckhdq, vpunpckhqdq, vpunpckhwd,
327362 vpunpcklbw, vpunpckldq, vpunpcklqdq, vpunpcklwd,
363 vpxor,
328364 vroundpd, vroundps, vroundsd, vroundss,
365 vshufpd, vshufps,
329366 vsqrtpd, vsqrtps, vsqrtsd, vsqrtss,
330367 vsubpd, vsubps, vsubsd, vsubss,
368 vxorpd, vxorps,
331369 // F16C
332370 vcvtph2ps, vcvtps2ph,
333371 // FMA
......@@ -368,80 +406,84 @@ pub const Op = enum {
368406 m,
369407 moffs,
370408 sreg,
409 st, mm, mm_m64,
371410 xmm, xmm_m32, xmm_m64, xmm_m128,
372411 ymm, ymm_m256,
373412 // zig fmt: on
374413
375414 pub fn fromOperand(operand: Instruction.Operand) Op {
376 switch (operand) {
377 .none => return .none,
378
379 .reg => |reg| {
380 switch (reg.class()) {
381 .segment => return .sreg,
382 .floating_point => return switch (reg.bitSize()) {
383 128 => .xmm,
384 256 => .ymm,
415 return switch (operand) {
416 .none => .none,
417
418 .reg => |reg| switch (reg.class()) {
419 .general_purpose => if (reg.to64() == .rax)
420 switch (reg) {
421 .al => .al,
422 .ax => .ax,
423 .eax => .eax,
424 .rax => .rax,
385425 else => unreachable,
386 },
387 .general_purpose => {
388 if (reg.to64() == .rax) return switch (reg) {
389 .al => .al,
390 .ax => .ax,
391 .eax => .eax,
392 .rax => .rax,
393 else => unreachable,
394 };
395 if (reg == .cl) return .cl;
396 return switch (reg.bitSize()) {
397 8 => .r8,
398 16 => .r16,
399 32 => .r32,
400 64 => .r64,
401 else => unreachable,
402 };
403 },
404 }
426 }
427 else if (reg == .cl)
428 .cl
429 else switch (reg.bitSize()) {
430 8 => .r8,
431 16 => .r16,
432 32 => .r32,
433 64 => .r64,
434 else => unreachable,
435 },
436 .segment => .sreg,
437 .x87 => .st,
438 .mmx => .mm,
439 .sse => switch (reg.bitSize()) {
440 128 => .xmm,
441 256 => .ymm,
442 else => unreachable,
443 },
405444 },
406445
407446 .mem => |mem| switch (mem) {
408 .moffs => return .moffs,
409 .sib, .rip => {
410 const bit_size = mem.bitSize();
411 return switch (bit_size) {
412 8 => .m8,
413 16 => .m16,
414 32 => .m32,
415 64 => .m64,
416 80 => .m80,
417 128 => .m128,
418 256 => .m256,
419 else => unreachable,
420 };
447 .moffs => .moffs,
448 .sib, .rip => switch (mem.bitSize()) {
449 8 => .m8,
450 16 => .m16,
451 32 => .m32,
452 64 => .m64,
453 80 => .m80,
454 128 => .m128,
455 256 => .m256,
456 else => unreachable,
421457 },
422458 },
423459
424 .imm => |imm| {
425 switch (imm) {
426 .signed => |x| {
427 if (x == 1) return .unity;
428 if (math.cast(i8, x)) |_| return .imm8s;
429 if (math.cast(i16, x)) |_| return .imm16s;
430 return .imm32s;
431 },
432 .unsigned => |x| {
433 if (x == 1) return .unity;
434 if (math.cast(i8, x)) |_| return .imm8s;
435 if (math.cast(u8, x)) |_| return .imm8;
436 if (math.cast(i16, x)) |_| return .imm16s;
437 if (math.cast(u16, x)) |_| return .imm16;
438 if (math.cast(i32, x)) |_| return .imm32s;
439 if (math.cast(u32, x)) |_| return .imm32;
440 return .imm64;
441 },
442 }
460 .imm => |imm| switch (imm) {
461 .signed => |x| if (x == 1)
462 .unity
463 else if (math.cast(i8, x)) |_|
464 .imm8s
465 else if (math.cast(i16, x)) |_|
466 .imm16s
467 else
468 .imm32s,
469 .unsigned => |x| if (x == 1)
470 .unity
471 else if (math.cast(i8, x)) |_|
472 .imm8s
473 else if (math.cast(u8, x)) |_|
474 .imm8
475 else if (math.cast(i16, x)) |_|
476 .imm16s
477 else if (math.cast(u16, x)) |_|
478 .imm16
479 else if (math.cast(i32, x)) |_|
480 .imm32s
481 else if (math.cast(u32, x)) |_|
482 .imm32
483 else
484 .imm64,
443485 },
444 }
486 };
445487 }
446488
447489 pub fn immBitSize(op: Op) u64 {
......@@ -451,6 +493,7 @@ pub const Op = enum {
451493 .ax, .r16, .rm16 => unreachable,
452494 .eax, .r32, .rm32, .r32_m16 => unreachable,
453495 .rax, .r64, .rm64, .r64_m16 => unreachable,
496 .st, .mm, .mm_m64 => unreachable,
454497 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => unreachable,
455498 .ymm, .ymm_m256 => unreachable,
456499 .m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable,
......@@ -471,7 +514,8 @@ pub const Op = enum {
471514 .al, .cl, .r8, .rm8 => 8,
472515 .ax, .r16, .rm16 => 16,
473516 .eax, .r32, .rm32, .r32_m8, .r32_m16 => 32,
474 .rax, .r64, .rm64, .r64_m16 => 64,
517 .rax, .r64, .rm64, .r64_m16, .mm, .mm_m64 => 64,
518 .st => 80,
475519 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => 128,
476520 .ymm, .ymm_m256 => 256,
477521 };
......@@ -482,11 +526,11 @@ pub const Op = enum {
482526 .none, .o16, .o32, .o64, .moffs, .m, .sreg => unreachable,
483527 .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable,
484528 .rel8, .rel16, .rel32 => unreachable,
485 .al, .cl, .r8, .ax, .r16, .eax, .r32, .rax, .r64, .xmm, .ymm => unreachable,
529 .al, .cl, .r8, .ax, .r16, .eax, .r32, .rax, .r64, .st, .mm, .xmm, .ymm => unreachable,
486530 .m8, .rm8, .r32_m8 => 8,
487531 .m16, .rm16, .r32_m16, .r64_m16 => 16,
488532 .m32, .rm32, .xmm_m32 => 32,
489 .m64, .rm64, .xmm_m64 => 64,
533 .m64, .rm64, .mm_m64, .xmm_m64 => 64,
490534 .m80 => 80,
491535 .m128, .xmm_m128 => 128,
492536 .m256, .ymm_m256 => 256,
......@@ -513,6 +557,7 @@ pub const Op = enum {
513557 .r8, .r16, .r32, .r64,
514558 .rm8, .rm16, .rm32, .rm64,
515559 .r32_m8, .r32_m16, .r64_m16,
560 .st, .mm, .mm_m64,
516561 .xmm, .xmm_m32, .xmm_m64, .xmm_m128,
517562 .ymm, .ymm_m256,
518563 => true,
......@@ -541,6 +586,7 @@ pub const Op = enum {
541586 .r32_m8, .r32_m16, .r64_m16,
542587 .m8, .m16, .m32, .m64, .m80, .m128, .m256,
543588 .m,
589 .mm_m64,
544590 .xmm_m32, .xmm_m64, .xmm_m128,
545591 .ymm_m256,
546592 => true,
......@@ -564,8 +610,10 @@ pub const Op = enum {
564610 .rm8, .rm16, .rm32, .rm64 => .general_purpose,
565611 .r32_m8, .r32_m16, .r64_m16 => .general_purpose,
566612 .sreg => .segment,
567 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => .floating_point,
568 .ymm, .ymm_m256 => .floating_point,
613 .st => .x87,
614 .mm, .mm_m64 => .mmx,
615 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => .sse,
616 .ymm, .ymm_m256 => .sse,
569617 };
570618 }
571619
......@@ -682,8 +730,12 @@ pub const Feature = enum {
682730 none,
683731 avx,
684732 avx2,
733 bmi,
685734 f16c,
686735 fma,
736 lzcnt,
737 movbe,
738 popcnt,
687739 sse,
688740 sse2,
689741 sse3,
......@@ -705,7 +757,7 @@ fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Op
705757}
706758
707759const mnemonic_to_encodings_map = init: {
708 @setEvalBranchQuota(20_000);
760 @setEvalBranchQuota(30_000);
709761 const encodings = @import("encodings.zig");
710762 var entries = encodings.table;
711763 std.sort.sort(encodings.Entry, &entries, {}, struct {
src/arch/x86_64/Lower.zig+115-16
......@@ -9,19 +9,33 @@ result_insts_len: u8 = undefined,
99result_relocs_len: u8 = undefined,
1010result_insts: [
1111 std.mem.max(usize, &.{
12 1, // non-pseudo instructions
1213 2, // cmovcc: cmovcc \ cmovcc
1314 3, // setcc: setcc \ setcc \ logicop
1415 2, // jcc: jcc \ jcc
16 pseudo_probe_align_insts,
17 pseudo_probe_adjust_unrolled_max_insts,
18 pseudo_probe_adjust_setup_insts,
19 pseudo_probe_adjust_loop_insts,
1520 abi.Win64.callee_preserved_regs.len, // push_regs/pop_regs
1621 abi.SysV.callee_preserved_regs.len, // push_regs/pop_regs
1722 })
1823]Instruction = undefined,
1924result_relocs: [
2025 std.mem.max(usize, &.{
26 1, // jmp/jcc/call/mov/lea: jmp/jcc/call/mov/lea
2127 2, // jcc: jcc \ jcc
28 2, // test \ jcc \ probe \ sub \ jmp
29 1, // probe \ sub \ jcc
2230 })
2331]Reloc = undefined,
2432
33pub const pseudo_probe_align_insts = 5; // test \ jcc \ probe \ sub \ jmp
34pub const pseudo_probe_adjust_unrolled_max_insts =
35 pseudo_probe_adjust_setup_insts + pseudo_probe_adjust_loop_insts;
36pub const pseudo_probe_adjust_setup_insts = 2; // mov \ sub
37pub const pseudo_probe_adjust_loop_insts = 3; // probe \ sub \ jcc
38
2539pub const Error = error{
2640 OutOfMemory,
2741 LowerFail,
......@@ -62,6 +76,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
6276 else => try lower.generic(inst),
6377 .pseudo => switch (inst.ops) {
6478 .pseudo_cmov_z_and_np_rr => {
79 assert(inst.data.rr.fixes == ._);
6580 try lower.emit(.none, .cmovnz, &.{
6681 .{ .reg = inst.data.rr.r2 },
6782 .{ .reg = inst.data.rr.r1 },
......@@ -72,6 +87,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
7287 });
7388 },
7489 .pseudo_cmov_nz_or_p_rr => {
90 assert(inst.data.rr.fixes == ._);
7591 try lower.emit(.none, .cmovnz, &.{
7692 .{ .reg = inst.data.rr.r1 },
7793 .{ .reg = inst.data.rr.r2 },
......@@ -84,6 +100,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
84100 .pseudo_cmov_nz_or_p_rm_sib,
85101 .pseudo_cmov_nz_or_p_rm_rip,
86102 => {
103 assert(inst.data.rx.fixes == ._);
87104 try lower.emit(.none, .cmovnz, &.{
88105 .{ .reg = inst.data.rx.r1 },
89106 .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
......@@ -94,58 +111,63 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
94111 });
95112 },
96113 .pseudo_set_z_and_np_r => {
114 assert(inst.data.rr.fixes == ._);
97115 try lower.emit(.none, .setz, &.{
98 .{ .reg = inst.data.r_scratch.r1 },
116 .{ .reg = inst.data.rr.r1 },
99117 });
100118 try lower.emit(.none, .setnp, &.{
101 .{ .reg = inst.data.r_scratch.scratch_reg },
119 .{ .reg = inst.data.rr.r2 },
102120 });
103121 try lower.emit(.none, .@"and", &.{
104 .{ .reg = inst.data.r_scratch.r1 },
105 .{ .reg = inst.data.r_scratch.scratch_reg },
122 .{ .reg = inst.data.rr.r1 },
123 .{ .reg = inst.data.rr.r2 },
106124 });
107125 },
108126 .pseudo_set_z_and_np_m_sib,
109127 .pseudo_set_z_and_np_m_rip,
110128 => {
129 assert(inst.data.rx.fixes == ._);
111130 try lower.emit(.none, .setz, &.{
112 .{ .mem = lower.mem(inst.ops, inst.data.x_scratch.payload) },
131 .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
113132 });
114133 try lower.emit(.none, .setnp, &.{
115 .{ .reg = inst.data.x_scratch.scratch_reg },
134 .{ .reg = inst.data.rx.r1 },
116135 });
117136 try lower.emit(.none, .@"and", &.{
118 .{ .mem = lower.mem(inst.ops, inst.data.x_scratch.payload) },
119 .{ .reg = inst.data.x_scratch.scratch_reg },
137 .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
138 .{ .reg = inst.data.rx.r1 },
120139 });
121140 },
122141 .pseudo_set_nz_or_p_r => {
142 assert(inst.data.rr.fixes == ._);
123143 try lower.emit(.none, .setnz, &.{
124 .{ .reg = inst.data.r_scratch.r1 },
144 .{ .reg = inst.data.rr.r1 },
125145 });
126146 try lower.emit(.none, .setp, &.{
127 .{ .reg = inst.data.r_scratch.scratch_reg },
147 .{ .reg = inst.data.rr.r2 },
128148 });
129149 try lower.emit(.none, .@"or", &.{
130 .{ .reg = inst.data.r_scratch.r1 },
131 .{ .reg = inst.data.r_scratch.scratch_reg },
150 .{ .reg = inst.data.rr.r1 },
151 .{ .reg = inst.data.rr.r2 },
132152 });
133153 },
134154 .pseudo_set_nz_or_p_m_sib,
135155 .pseudo_set_nz_or_p_m_rip,
136156 => {
157 assert(inst.data.rx.fixes == ._);
137158 try lower.emit(.none, .setnz, &.{
138 .{ .mem = lower.mem(inst.ops, inst.data.x_scratch.payload) },
159 .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
139160 });
140161 try lower.emit(.none, .setp, &.{
141 .{ .reg = inst.data.x_scratch.scratch_reg },
162 .{ .reg = inst.data.rx.r1 },
142163 });
143164 try lower.emit(.none, .@"or", &.{
144 .{ .mem = lower.mem(inst.ops, inst.data.x_scratch.payload) },
145 .{ .reg = inst.data.x_scratch.scratch_reg },
165 .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
166 .{ .reg = inst.data.rx.r1 },
146167 });
147168 },
148169 .pseudo_j_z_and_np_inst => {
170 assert(inst.data.inst.fixes == ._);
149171 try lower.emit(.none, .jnz, &.{
150172 .{ .imm = lower.reloc(.{ .inst = index + 1 }) },
151173 });
......@@ -154,6 +176,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
154176 });
155177 },
156178 .pseudo_j_nz_or_p_inst => {
179 assert(inst.data.inst.fixes == ._);
157180 try lower.emit(.none, .jnz, &.{
158181 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
159182 });
......@@ -162,6 +185,78 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
162185 });
163186 },
164187
188 .pseudo_probe_align_ri_s => {
189 try lower.emit(.none, .@"test", &.{
190 .{ .reg = inst.data.ri.r1 },
191 .{ .imm = Immediate.s(@bitCast(i32, inst.data.ri.i)) },
192 });
193 try lower.emit(.none, .jz, &.{
194 .{ .imm = lower.reloc(.{ .inst = index + 1 }) },
195 });
196 try lower.emit(.none, .lea, &.{
197 .{ .reg = inst.data.ri.r1 },
198 .{ .mem = Memory.sib(.qword, .{
199 .base = .{ .reg = inst.data.ri.r1 },
200 .disp = -page_size,
201 }) },
202 });
203 try lower.emit(.none, .@"test", &.{
204 .{ .mem = Memory.sib(.dword, .{
205 .base = .{ .reg = inst.data.ri.r1 },
206 }) },
207 .{ .reg = inst.data.ri.r1.to32() },
208 });
209 try lower.emit(.none, .jmp, &.{
210 .{ .imm = lower.reloc(.{ .inst = index }) },
211 });
212 assert(lower.result_insts_len == pseudo_probe_align_insts);
213 },
214 .pseudo_probe_adjust_unrolled_ri_s => {
215 var offset = page_size;
216 while (offset < @bitCast(i32, inst.data.ri.i)) : (offset += page_size) {
217 try lower.emit(.none, .@"test", &.{
218 .{ .mem = Memory.sib(.dword, .{
219 .base = .{ .reg = inst.data.ri.r1 },
220 .disp = -offset,
221 }) },
222 .{ .reg = inst.data.ri.r1.to32() },
223 });
224 }
225 try lower.emit(.none, .sub, &.{
226 .{ .reg = inst.data.ri.r1 },
227 .{ .imm = Immediate.s(@bitCast(i32, inst.data.ri.i)) },
228 });
229 assert(lower.result_insts_len <= pseudo_probe_adjust_unrolled_max_insts);
230 },
231 .pseudo_probe_adjust_setup_rri_s => {
232 try lower.emit(.none, .mov, &.{
233 .{ .reg = inst.data.rri.r2.to32() },
234 .{ .imm = Immediate.s(@bitCast(i32, inst.data.rri.i)) },
235 });
236 try lower.emit(.none, .sub, &.{
237 .{ .reg = inst.data.rri.r1 },
238 .{ .reg = inst.data.rri.r2 },
239 });
240 assert(lower.result_insts_len == pseudo_probe_adjust_setup_insts);
241 },
242 .pseudo_probe_adjust_loop_rr => {
243 try lower.emit(.none, .@"test", &.{
244 .{ .mem = Memory.sib(.dword, .{
245 .base = .{ .reg = inst.data.rr.r1 },
246 .scale_index = .{ .scale = 1, .index = inst.data.rr.r2 },
247 .disp = -page_size,
248 }) },
249 .{ .reg = inst.data.rr.r1.to32() },
250 });
251 try lower.emit(.none, .sub, &.{
252 .{ .reg = inst.data.rr.r2 },
253 .{ .imm = Immediate.s(page_size) },
254 });
255 try lower.emit(.none, .jae, &.{
256 .{ .imm = lower.reloc(.{ .inst = index }) },
257 });
258 assert(lower.result_insts_len == pseudo_probe_adjust_loop_insts);
259 },
165260 .pseudo_push_reg_list => try lower.pushPopRegList(.push, inst),
166261 .pseudo_pop_reg_list => try lower.pushPopRegList(.pop, inst),
167262
......@@ -300,6 +395,8 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
300395 else
301396 .none,
302397 }, mnemonic: {
398 @setEvalBranchQuota(2_000);
399
303400 comptime var max_len = 0;
304401 inline for (@typeInfo(Mnemonic).Enum.fields) |field| max_len = @max(field.name.len, max_len);
305402 var buf: [max_len]u8 = undefined;
......@@ -438,6 +535,8 @@ fn pushPopRegList(lower: *Lower, comptime mnemonic: Mnemonic, inst: Mir.Inst) Er
438535 }});
439536}
440537
538const page_size: i32 = 1 << 12;
539
441540const abi = @import("abi.zig");
442541const assert = std.debug.assert;
443542const bits = @import("bits.zig");
src/arch/x86_64/Mir.zig+108-24
......@@ -236,6 +236,14 @@ pub const Inst = struct {
236236
237237 /// VEX-Encoded ___
238238 v_,
239 /// VEX-Encoded ___ Byte
240 v_b,
241 /// VEX-Encoded ___ Word
242 v_w,
243 /// VEX-Encoded ___ Doubleword
244 v_d,
245 /// VEX-Encoded ___ QuadWord
246 v_q,
239247 /// VEX-Encoded Packed ___
240248 vp_,
241249 /// VEX-Encoded Packed ___ Byte
......@@ -256,6 +264,8 @@ pub const Inst = struct {
256264 v_sd,
257265 /// VEX-Encoded ___ Packed Double-Precision Values
258266 v_pd,
267 /// VEX-Encoded ___ 128-Bits Of Floating-Point Data
268 v_f128,
259269
260270 /// Mask ___ Byte
261271 k_b,
......@@ -278,6 +288,7 @@ pub const Inst = struct {
278288 /// Add with carry
279289 adc,
280290 /// Add
291 /// Add packed integers
281292 /// Add packed single-precision floating-point values
282293 /// Add scalar single-precision floating-point values
283294 /// Add packed double-precision floating-point values
......@@ -410,6 +421,7 @@ pub const Inst = struct {
410421 /// Double precision shift right
411422 sh,
412423 /// Subtract
424 /// Subtract packed integers
413425 /// Subtract packed single-precision floating-point values
414426 /// Subtract scalar single-precision floating-point values
415427 /// Subtract packed double-precision floating-point values
......@@ -434,11 +446,45 @@ pub const Inst = struct {
434446 /// Bitwise logical xor of packed double-precision floating-point values
435447 xor,
436448
449 /// Add packed signed integers with signed saturation
450 adds,
451 /// Add packed unsigned integers with unsigned saturation
452 addus,
437453 /// Bitwise logical and not of packed single-precision floating-point values
438454 /// Bitwise logical and not of packed double-precision floating-point values
439455 andn,
456 /// Maximum of packed signed integers
457 maxs,
458 /// Maximum of packed unsigned integers
459 maxu,
460 /// Minimum of packed signed integers
461 mins,
462 /// Minimum of packed unsigned integers
463 minu,
464 /// Multiply packed signed integers and store low result
465 mull,
466 /// Multiply packed signed integers and store high result
467 mulh,
468 /// Subtract packed signed integers with signed saturation
469 subs,
470 /// Subtract packed unsigned integers with unsigned saturation
471 subus,
472
473 /// Convert packed doubleword integers to packed single-precision floating-point values
474 /// Convert packed doubleword integers to packed double-precision floating-point values
475 cvtpi2,
476 /// Convert packed single-precision floating-point values to packed doubleword integers
477 cvtps2pi,
440478 /// Convert doubleword integer to scalar single-precision floating-point value
441 cvtsi2ss,
479 /// Convert doubleword integer to scalar double-precision floating-point value
480 cvtsi2,
481 /// Convert scalar single-precision floating-point value to doubleword integer
482 cvtss2si,
483 /// Convert with truncation packed single-precision floating-point values to packed doubleword integers
484 cvttps2pi,
485 /// Convert with truncation scalar single-precision floating-point value to doubleword integer
486 cvttss2si,
487
442488 /// Maximum of packed single-precision floating-point values
443489 /// Maximum of scalar single-precision floating-point values
444490 /// Maximum of packed double-precision floating-point values
......@@ -454,6 +500,8 @@ pub const Inst = struct {
454500 mova,
455501 /// Move packed single-precision floating-point values high to low
456502 movhl,
503 /// Move packed single-precision floating-point values low to high
504 movlh,
457505 /// Move unaligned packed single-precision floating-point values
458506 /// Move unaligned packed double-precision floating-point values
459507 movu,
......@@ -482,12 +530,40 @@ pub const Inst = struct {
482530 /// Unpack and interleave low packed double-precision floating-point values
483531 unpckl,
484532
533 /// Convert packed doubleword integers to packed single-precision floating-point values
534 /// Convert packed doubleword integers to packed double-precision floating-point values
535 cvtdq2,
536 /// Convert packed double-precision floating-point values to packed doubleword integers
537 cvtpd2dq,
538 /// Convert packed double-precision floating-point values to packed doubleword integers
539 cvtpd2pi,
540 /// Convert packed double-precision floating-point values to packed single-precision floating-point values
541 cvtpd2,
542 /// Convert packed single-precision floating-point values to packed doubleword integers
543 cvtps2dq,
544 /// Convert packed single-precision floating-point values to packed double-precision floating-point values
545 cvtps2,
546 /// Convert scalar double-precision floating-point value to doubleword integer
547 cvtsd2si,
485548 /// Convert scalar double-precision floating-point value to scalar single-precision floating-point value
486 cvtsd2ss,
487 /// Convert doubleword integer to scalar double-precision floating-point value
488 cvtsi2sd,
549 cvtsd2,
489550 /// Convert scalar single-precision floating-point value to scalar double-precision floating-point value
490 cvtss2sd,
551 cvtss2,
552 /// Convert with truncation packed double-precision floating-point values to packed doubleword integers
553 cvttpd2dq,
554 /// Convert with truncation packed double-precision floating-point values to packed doubleword integers
555 cvttpd2pi,
556 /// Convert with truncation packed single-precision floating-point values to packed doubleword integers
557 cvttps2dq,
558 /// Convert with truncation scalar double-precision floating-point value to doubleword integer
559 cvttsd2si,
560 /// Move aligned packed integer values
561 movdqa,
562 /// Move unaligned packed integer values
563 movdqu,
564 /// Packed interleave shuffle of quadruplets of single-precision floating-point values
565 /// Packed interleave shuffle of pairs of double-precision floating-point values
566 shuf,
491567 /// Shuffle packed high words
492568 shufh,
493569 /// Shuffle packed low words
......@@ -520,14 +596,22 @@ pub const Inst = struct {
520596 /// Replicate single floating-point values
521597 movsldup,
522598
599 /// Extract packed floating-point values
600 extract,
601 /// Insert scalar single-precision floating-point value
602 /// Insert packed floating-point values
603 insert,
523604 /// Round packed single-precision floating-point values
524605 /// Round scalar single-precision floating-point value
525606 /// Round packed double-precision floating-point values
526607 /// Round scalar double-precision floating-point value
527608 round,
528609
610 /// Load with broadcast floating-point data
611 broadcast,
612
529613 /// Convert 16-bit floating-point values to single-precision floating-point values
530 cvtph2ps,
614 cvtph2,
531615 /// Convert single-precision floating-point values to 16-bit floating-point values
532616 cvtps2ph,
533617
......@@ -696,27 +780,27 @@ pub const Inst = struct {
696780 pseudo_cmov_nz_or_p_rm_rip,
697781 /// Set byte if zero flag set and parity flag not set
698782 /// Requires a scratch register!
699 /// Uses `r_scratch` payload.
783 /// Uses `rr` payload.
700784 pseudo_set_z_and_np_r,
701785 /// Set byte if zero flag set and parity flag not set
702786 /// Requires a scratch register!
703 /// Uses `x_scratch` payload.
787 /// Uses `rx` payload.
704788 pseudo_set_z_and_np_m_sib,
705789 /// Set byte if zero flag set and parity flag not set
706790 /// Requires a scratch register!
707 /// Uses `x_scratch` payload.
791 /// Uses `rx` payload.
708792 pseudo_set_z_and_np_m_rip,
709793 /// Set byte if zero flag not set or parity flag set
710794 /// Requires a scratch register!
711 /// Uses `r_scratch` payload.
795 /// Uses `rr` payload.
712796 pseudo_set_nz_or_p_r,
713797 /// Set byte if zero flag not set or parity flag set
714798 /// Requires a scratch register!
715 /// Uses `x_scratch` payload.
799 /// Uses `rx` payload.
716800 pseudo_set_nz_or_p_m_sib,
717801 /// Set byte if zero flag not set or parity flag set
718802 /// Requires a scratch register!
719 /// Uses `x_scratch` payload.
803 /// Uses `rx` payload.
720804 pseudo_set_nz_or_p_m_rip,
721805 /// Jump if zero flag set and parity flag not set
722806 /// Uses `inst` payload.
......@@ -725,6 +809,18 @@ pub const Inst = struct {
725809 /// Uses `inst` payload.
726810 pseudo_j_nz_or_p_inst,
727811
812 /// Probe alignment
813 /// Uses `ri` payload
814 pseudo_probe_align_ri_s,
815 /// Probe adjust unrolled
816 /// Uses `ri` payload
817 pseudo_probe_adjust_unrolled_ri_s,
818 /// Probe adjust setup
819 /// Uses `rri` payload
820 pseudo_probe_adjust_setup_rri_s,
821 /// Probe adjust loop
822 /// Uses `rr` payload
823 pseudo_probe_adjust_loop_rr,
728824 /// Push registers
729825 /// Uses `reg_list` payload.
730826 pseudo_push_reg_list,
......@@ -821,18 +917,6 @@ pub const Inst = struct {
821917 i: u8,
822918 payload: u32,
823919 },
824 /// Register, scratch register
825 r_scratch: struct {
826 fixes: Fixes = ._,
827 r1: Register,
828 scratch_reg: Register,
829 },
830 /// Scratch register, followed by Custom payload found in extra.
831 x_scratch: struct {
832 fixes: Fixes = ._,
833 scratch_reg: Register,
834 payload: u32,
835 },
836920 /// Custom payload found in extra.
837921 x: struct {
838922 fixes: Fixes = ._,
src/arch/x86_64/abi.zig+2-28
......@@ -165,34 +165,6 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
165165 },
166166 .Vector => {
167167 const elem_ty = ty.childType();
168 if (ctx == .arg) {
169 const bit_size = ty.bitSize(target);
170 if (bit_size > 128) {
171 const has_avx512 = target.cpu.features.isEnabled(@enumToInt(std.Target.x86.Feature.avx512f));
172 if (has_avx512 and bit_size <= 512) return .{
173 .integer, .integer, .integer, .integer,
174 .integer, .integer, .integer, .integer,
175 };
176 const has_avx = target.cpu.features.isEnabled(@enumToInt(std.Target.x86.Feature.avx));
177 if (has_avx and bit_size <= 256) return .{
178 .integer, .integer, .integer, .integer,
179 .none, .none, .none, .none,
180 };
181 return memory_class;
182 }
183 if (bit_size > 80) return .{
184 .integer, .integer, .none, .none,
185 .none, .none, .none, .none,
186 };
187 if (bit_size > 64) return .{
188 .x87, .none, .none, .none,
189 .none, .none, .none, .none,
190 };
191 return .{
192 .integer, .none, .none, .none,
193 .none, .none, .none, .none,
194 };
195 }
196168 const bits = elem_ty.bitSize(target) * ty.arrayLen();
197169 if (bits <= 64) return .{
198170 .sse, .none, .none, .none,
......@@ -202,6 +174,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
202174 .sse, .sseup, .none, .none,
203175 .none, .none, .none, .none,
204176 };
177 if (ctx == .arg and !std.Target.x86.featureSetHas(target.cpu.features, .avx)) return memory_class;
205178 if (bits <= 192) return .{
206179 .sse, .sseup, .sseup, .none,
207180 .none, .none, .none, .none,
......@@ -210,6 +183,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
210183 .sse, .sseup, .sseup, .sseup,
211184 .none, .none, .none, .none,
212185 };
186 if (ctx == .arg and !std.Target.x86.featureSetHas(target.cpu.features, .avx512f)) return memory_class;
213187 if (bits <= 320) return .{
214188 .sse, .sseup, .sseup, .sseup,
215189 .sseup, .none, .none, .none,
src/arch/x86_64/bits.zig+38-45
......@@ -175,15 +175,21 @@ pub const Register = enum(u7) {
175175 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
176176 xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
177177
178 mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
179
180 st0, st1, st2, st3, st4, st5, st6, st7,
181
178182 es, cs, ss, ds, fs, gs,
179183
180184 none,
181185 // zig fmt: on
182186
183 pub const Class = enum(u2) {
187 pub const Class = enum {
184188 general_purpose,
185 floating_point,
186189 segment,
190 x87,
191 mmx,
192 sse,
187193 };
188194
189195 pub fn class(reg: Register) Class {
......@@ -195,8 +201,10 @@ pub const Register = enum(u7) {
195201 @enumToInt(Register.al) ... @enumToInt(Register.r15b) => .general_purpose,
196202 @enumToInt(Register.ah) ... @enumToInt(Register.bh) => .general_purpose,
197203
198 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => .floating_point,
199 @enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => .floating_point,
204 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => .sse,
205 @enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => .sse,
206 @enumToInt(Register.mm0) ... @enumToInt(Register.mm7) => .mmx,
207 @enumToInt(Register.st0) ... @enumToInt(Register.st7) => .x87,
200208
201209 @enumToInt(Register.es) ... @enumToInt(Register.gs) => .segment,
202210
......@@ -216,8 +224,10 @@ pub const Register = enum(u7) {
216224
217225 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => @enumToInt(Register.ymm0) - 16,
218226 @enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => @enumToInt(Register.xmm0) - 16,
227 @enumToInt(Register.mm0) ... @enumToInt(Register.mm7) => @enumToInt(Register.mm0) - 32,
228 @enumToInt(Register.st0) ... @enumToInt(Register.st7) => @enumToInt(Register.st0) - 40,
219229
220 @enumToInt(Register.es) ... @enumToInt(Register.gs) => @enumToInt(Register.es) - 32,
230 @enumToInt(Register.es) ... @enumToInt(Register.gs) => @enumToInt(Register.es) - 48,
221231
222232 else => unreachable,
223233 // zig fmt: on
......@@ -236,6 +246,8 @@ pub const Register = enum(u7) {
236246
237247 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => 256,
238248 @enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => 128,
249 @enumToInt(Register.mm0) ... @enumToInt(Register.mm7) => 64,
250 @enumToInt(Register.st0) ... @enumToInt(Register.st7) => 80,
239251
240252 @enumToInt(Register.es) ... @enumToInt(Register.gs) => 16,
241253
......@@ -271,6 +283,8 @@ pub const Register = enum(u7) {
271283
272284 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => @enumToInt(Register.ymm0),
273285 @enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => @enumToInt(Register.xmm0),
286 @enumToInt(Register.mm0) ... @enumToInt(Register.mm7) => @enumToInt(Register.mm0),
287 @enumToInt(Register.st0) ... @enumToInt(Register.st7) => @enumToInt(Register.st0),
274288
275289 @enumToInt(Register.es) ... @enumToInt(Register.gs) => @enumToInt(Register.es),
276290
......@@ -326,8 +340,8 @@ pub const Register = enum(u7) {
326340 return @intToEnum(Register, @enumToInt(reg) - reg.gpBase() + @enumToInt(Register.al));
327341 }
328342
329 fn fpBase(reg: Register) u7 {
330 assert(reg.class() == .floating_point);
343 fn sseBase(reg: Register) u7 {
344 assert(reg.class() == .sse);
331345 return switch (@enumToInt(reg)) {
332346 @enumToInt(Register.ymm0)...@enumToInt(Register.ymm15) => @enumToInt(Register.ymm0),
333347 @enumToInt(Register.xmm0)...@enumToInt(Register.xmm15) => @enumToInt(Register.xmm0),
......@@ -336,49 +350,24 @@ pub const Register = enum(u7) {
336350 }
337351
338352 pub fn to256(reg: Register) Register {
339 return @intToEnum(Register, @enumToInt(reg) - reg.fpBase() + @enumToInt(Register.ymm0));
353 return @intToEnum(Register, @enumToInt(reg) - reg.sseBase() + @enumToInt(Register.ymm0));
340354 }
341355
342356 pub fn to128(reg: Register) Register {
343 return @intToEnum(Register, @enumToInt(reg) - reg.fpBase() + @enumToInt(Register.xmm0));
344 }
345
346 pub fn dwarfLocOp(reg: Register) u8 {
347 return switch (reg.class()) {
348 .general_purpose => switch (reg.to64()) {
349 .rax => DW.OP.reg0,
350 .rdx => DW.OP.reg1,
351 .rcx => DW.OP.reg2,
352 .rbx => DW.OP.reg3,
353 .rsi => DW.OP.reg4,
354 .rdi => DW.OP.reg5,
355 .rbp => DW.OP.reg6,
356 .rsp => DW.OP.reg7,
357 else => @intCast(u8, @enumToInt(reg) - reg.gpBase()) + DW.OP.reg0,
358 },
359 .floating_point => @intCast(u8, @enumToInt(reg) - reg.fpBase()) + DW.OP.reg17,
360 else => unreachable,
361 };
357 return @intToEnum(Register, @enumToInt(reg) - reg.sseBase() + @enumToInt(Register.xmm0));
362358 }
363359
364 /// DWARF encodings that push a value onto the DWARF stack that is either
365 /// the contents of a register or the result of adding the contents a given
366 /// register to a given signed offset.
367 pub fn dwarfLocOpDeref(reg: Register) u8 {
360 /// DWARF register encoding
361 pub fn dwarfNum(reg: Register) u6 {
368362 return switch (reg.class()) {
369 .general_purpose => switch (reg.to64()) {
370 .rax => DW.OP.breg0,
371 .rdx => DW.OP.breg1,
372 .rcx => DW.OP.breg2,
373 .rbx => DW.OP.breg3,
374 .rsi => DW.OP.breg4,
375 .rdi => DW.OP.breg5,
376 .rbp => DW.OP.breg6,
377 .rsp => DW.OP.breg7,
378 else => @intCast(u8, @enumToInt(reg) - reg.gpBase()) + DW.OP.breg0,
379 },
380 .floating_point => @intCast(u8, @enumToInt(reg) - reg.fpBase()) + DW.OP.breg17,
381 else => unreachable,
363 .general_purpose => if (reg.isExtended())
364 reg.enc()
365 else
366 @truncate(u3, @as(u24, 0o54673120) >> @as(u5, reg.enc()) * 3),
367 .sse => 17 + @as(u6, reg.enc()),
368 .x87 => 33 + @as(u6, reg.enc()),
369 .mmx => 41 + @as(u6, reg.enc()),
370 .segment => 50 + @as(u6, reg.enc()),
382371 };
383372 }
384373};
......@@ -392,6 +381,8 @@ test "Register id - different classes" {
392381 try expect(Register.ymm0.id() == 0b10000);
393382 try expect(Register.ymm0.id() != Register.rax.id());
394383 try expect(Register.xmm0.id() == Register.ymm0.id());
384 try expect(Register.xmm0.id() != Register.mm0.id());
385 try expect(Register.mm0.id() != Register.st0.id());
395386
396387 try expect(Register.es.id() == 0b100000);
397388}
......@@ -407,7 +398,9 @@ test "Register enc - different classes" {
407398
408399test "Register classes" {
409400 try expect(Register.r11.class() == .general_purpose);
410 try expect(Register.ymm11.class() == .floating_point);
401 try expect(Register.ymm11.class() == .sse);
402 try expect(Register.mm3.class() == .mmx);
403 try expect(Register.st3.class() == .x87);
411404 try expect(Register.fs.class() == .segment);
412405}
413406
src/arch/x86_64/encodings.zig+359-31
......@@ -272,14 +272,6 @@ pub const table = [_]Entry{
272272 .{ .div, .m, &.{ .rm32 }, &.{ 0xf7 }, 6, .none, .none },
273273 .{ .div, .m, &.{ .rm64 }, &.{ 0xf7 }, 6, .long, .none },
274274
275 .{ .fisttp, .m, &.{ .m16 }, &.{ 0xdf }, 1, .none, .x87 },
276 .{ .fisttp, .m, &.{ .m32 }, &.{ 0xdb }, 1, .none, .x87 },
277 .{ .fisttp, .m, &.{ .m64 }, &.{ 0xdd }, 1, .none, .x87 },
278
279 .{ .fld, .m, &.{ .m32 }, &.{ 0xd9 }, 0, .none, .x87 },
280 .{ .fld, .m, &.{ .m64 }, &.{ 0xdd }, 0, .none, .x87 },
281 .{ .fld, .m, &.{ .m80 }, &.{ 0xdb }, 5, .none, .x87 },
282
283275 .{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .none, .none },
284276 .{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .rex, .none },
285277 .{ .idiv, .m, &.{ .rm16 }, &.{ 0xf7 }, 7, .short, .none },
......@@ -354,9 +346,9 @@ pub const table = [_]Entry{
354346 .{ .lodsd, .np, &.{}, &.{ 0xad }, 0, .none, .none },
355347 .{ .lodsq, .np, &.{}, &.{ 0xad }, 0, .long, .none },
356348
357 .{ .lzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .short, .none },
358 .{ .lzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .none, .none },
359 .{ .lzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .long, .none },
349 .{ .lzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .short, .lzcnt },
350 .{ .lzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .none, .lzcnt },
351 .{ .lzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .long, .lzcnt },
360352
361353 .{ .mfence, .np, &.{}, &.{ 0x0f, 0xae, 0xf0 }, 0, .none, .none },
362354
......@@ -395,12 +387,12 @@ pub const table = [_]Entry{
395387 .{ .mov, .mi, &.{ .rm32, .imm32 }, &.{ 0xc7 }, 0, .none, .none },
396388 .{ .mov, .mi, &.{ .rm64, .imm32s }, &.{ 0xc7 }, 0, .long, .none },
397389
398 .{ .movbe, .rm, &.{ .r16, .m16 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .short, .none },
399 .{ .movbe, .rm, &.{ .r32, .m32 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .none, .none },
400 .{ .movbe, .rm, &.{ .r64, .m64 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .long, .none },
401 .{ .movbe, .mr, &.{ .m16, .r16 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .short, .none },
402 .{ .movbe, .mr, &.{ .m32, .r32 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none, .none },
403 .{ .movbe, .mr, &.{ .m64, .r64 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .long, .none },
390 .{ .movbe, .rm, &.{ .r16, .m16 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .short, .movbe },
391 .{ .movbe, .rm, &.{ .r32, .m32 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .none, .movbe },
392 .{ .movbe, .rm, &.{ .r64, .m64 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .long, .movbe },
393 .{ .movbe, .mr, &.{ .m16, .r16 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .short, .movbe },
394 .{ .movbe, .mr, &.{ .m32, .r32 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none, .movbe },
395 .{ .movbe, .mr, &.{ .m64, .r64 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .long, .movbe },
404396
405397 .{ .movs, .np, &.{ .m8, .m8 }, &.{ 0xa4 }, 0, .none, .none },
406398 .{ .movs, .np, &.{ .m16, .m16 }, &.{ 0xa5 }, 0, .short, .none },
......@@ -482,9 +474,9 @@ pub const table = [_]Entry{
482474 .{ .pop, .m, &.{ .rm16 }, &.{ 0x8f }, 0, .short, .none },
483475 .{ .pop, .m, &.{ .rm64 }, &.{ 0x8f }, 0, .none, .none },
484476
485 .{ .popcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .short, .none },
486 .{ .popcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none, .none },
487 .{ .popcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long, .none },
477 .{ .popcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .short, .popcnt },
478 .{ .popcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none, .popcnt },
479 .{ .popcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long, .popcnt },
488480
489481 .{ .push, .o, &.{ .r16 }, &.{ 0x50 }, 0, .short, .none },
490482 .{ .push, .o, &.{ .r64 }, &.{ 0x50 }, 0, .none, .none },
......@@ -784,9 +776,9 @@ pub const table = [_]Entry{
784776 .{ .@"test", .mr, &.{ .rm32, .r32 }, &.{ 0x85 }, 0, .none, .none },
785777 .{ .@"test", .mr, &.{ .rm64, .r64 }, &.{ 0x85 }, 0, .long, .none },
786778
787 .{ .tzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .short, .none },
788 .{ .tzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .none, .none },
789 .{ .tzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .long, .none },
779 .{ .tzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .short, .bmi },
780 .{ .tzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .none, .bmi },
781 .{ .tzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .long, .bmi },
790782
791783 .{ .ud2, .np, &.{}, &.{ 0x0f, 0x0b }, 0, .none, .none },
792784
......@@ -836,6 +828,15 @@ pub const table = [_]Entry{
836828 .{ .xor, .rm, &.{ .r32, .rm32 }, &.{ 0x33 }, 0, .none, .none },
837829 .{ .xor, .rm, &.{ .r64, .rm64 }, &.{ 0x33 }, 0, .long, .none },
838830
831 // X87
832 .{ .fisttp, .m, &.{ .m16 }, &.{ 0xdf }, 1, .none, .x87 },
833 .{ .fisttp, .m, &.{ .m32 }, &.{ 0xdb }, 1, .none, .x87 },
834 .{ .fisttp, .m, &.{ .m64 }, &.{ 0xdd }, 1, .none, .x87 },
835
836 .{ .fld, .m, &.{ .m32 }, &.{ 0xd9 }, 0, .none, .x87 },
837 .{ .fld, .m, &.{ .m64 }, &.{ 0xdd }, 0, .none, .x87 },
838 .{ .fld, .m, &.{ .m80 }, &.{ 0xdb }, 5, .none, .x87 },
839
839840 // SSE
840841 .{ .addps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x58 }, 0, .none, .sse },
841842
......@@ -847,9 +848,21 @@ pub const table = [_]Entry{
847848
848849 .{ .cmpss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0xf3, 0x0f, 0xc2 }, 0, .none, .sse },
849850
851 .{ .cvtpi2ps, .rm, &.{ .xmm, .mm_m64 }, &.{ 0x0f, 0x2a }, 0, .none, .sse },
852
853 .{ .cvtps2pi, .rm, &.{ .mm, .xmm_m64 }, &.{ 0x0f, 0x2d }, 0, .none, .sse },
854
850855 .{ .cvtsi2ss, .rm, &.{ .xmm, .rm32 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .none, .sse },
851856 .{ .cvtsi2ss, .rm, &.{ .xmm, .rm64 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .long, .sse },
852857
858 .{ .cvtss2si, .rm, &.{ .r32, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2d }, 0, .none, .sse },
859 .{ .cvtss2si, .rm, &.{ .r64, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2d }, 0, .long, .sse },
860
861 .{ .cvttps2pi, .rm, &.{ .mm, .xmm_m64 }, &.{ 0x0f, 0x2c }, 0, .none, .sse },
862
863 .{ .cvttss2si, .rm, &.{ .r32, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2c }, 0, .none, .sse },
864 .{ .cvttss2si, .rm, &.{ .r64, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2c }, 0, .long, .sse },
865
853866 .{ .divps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5e }, 0, .none, .sse },
854867
855868 .{ .divss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5e }, 0, .none, .sse },
......@@ -867,6 +880,8 @@ pub const table = [_]Entry{
867880
868881 .{ .movhlps, .rm, &.{ .xmm, .xmm }, &.{ 0x0f, 0x12 }, 0, .none, .sse },
869882
883 .{ .movlhps, .rm, &.{ .xmm, .xmm }, &.{ 0x0f, 0x16 }, 0, .none, .sse },
884
870885 .{ .movss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x10 }, 0, .none, .sse },
871886 .{ .movss, .mr, &.{ .xmm_m32, .xmm }, &.{ 0xf3, 0x0f, 0x11 }, 0, .none, .sse },
872887
......@@ -879,14 +894,16 @@ pub const table = [_]Entry{
879894
880895 .{ .orps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x56 }, 0, .none, .sse },
881896
882 .{ .subps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5c }, 0, .none, .sse },
883
884 .{ .subss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .none, .sse },
897 .{ .shufps, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x0f, 0xc6 }, 0, .none, .sse },
885898
886899 .{ .sqrtps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x51 }, 0, .none, .sse },
887900
888901 .{ .sqrtss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x51 }, 0, .none, .sse },
889902
903 .{ .subps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5c }, 0, .none, .sse },
904
905 .{ .subss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .none, .sse },
906
890907 .{ .ucomiss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0x0f, 0x2e }, 0, .none, .sse },
891908
892909 .{ .xorps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x57 }, 0, .none, .sse },
......@@ -902,6 +919,25 @@ pub const table = [_]Entry{
902919
903920 .{ .cmpsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0xf2, 0x0f, 0xc2 }, 0, .none, .sse2 },
904921
922 .{ .cvtdq2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0xe6 }, 0, .none, .sse2 },
923
924 .{ .cvtdq2ps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5b }, 0, .none, .sse2 },
925
926 .{ .cvtpd2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf2, 0x0f, 0xe6 }, 0, .none, .sse2 },
927
928 .{ .cvtpd2pi, .rm, &.{ .mm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x2d }, 0, .none, .sse2 },
929
930 .{ .cvtpd2ps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5a }, 0, .none, .sse2 },
931
932 .{ .cvtpi2pd, .rm, &.{ .xmm, .mm_m64 }, &.{ 0x66, 0x0f, 0x2a }, 0, .none, .sse2 },
933
934 .{ .cvtps2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5b }, 0, .none, .sse2 },
935
936 .{ .cvtps2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x0f, 0x5a }, 0, .none, .sse2 },
937
938 .{ .cvtsd2si, .rm, &.{ .r32, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2d }, 0, .none, .sse2 },
939 .{ .cvtsd2si, .rm, &.{ .r64, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2d }, 0, .long, .sse2 },
940
905941 .{ .cvtsd2ss, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .none, .sse2 },
906942
907943 .{ .cvtsi2sd, .rm, &.{ .xmm, .rm32 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .none, .sse2 },
......@@ -909,6 +945,15 @@ pub const table = [_]Entry{
909945
910946 .{ .cvtss2sd, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5a }, 0, .none, .sse2 },
911947
948 .{ .cvttpd2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xe6 }, 0, .none, .sse2 },
949
950 .{ .cvttpd2pi, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x2c }, 0, .none, .sse2 },
951
952 .{ .cvttps2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0x5b }, 0, .none, .sse2 },
953
954 .{ .cvttsd2si, .rm, &.{ .r32, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2c }, 0, .none, .sse2 },
955 .{ .cvttsd2si, .rm, &.{ .r64, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2c }, 0, .long, .sse2 },
956
912957 .{ .divpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5e }, 0, .none, .sse2 },
913958
914959 .{ .divsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5e }, 0, .none, .sse2 },
......@@ -925,11 +970,16 @@ pub const table = [_]Entry{
925970 .{ .movapd, .mr, &.{ .xmm_m128, .xmm }, &.{ 0x66, 0x0f, 0x29 }, 0, .none, .sse2 },
926971
927972 .{ .movd, .rm, &.{ .xmm, .rm32 }, &.{ 0x66, 0x0f, 0x6e }, 0, .none, .sse2 },
928 .{ .movd, .mr, &.{ .rm32, .xmm }, &.{ 0x66, 0x0f, 0x7e }, 0, .none, .sse2 },
929
930973 .{ .movq, .rm, &.{ .xmm, .rm64 }, &.{ 0x66, 0x0f, 0x6e }, 0, .long, .sse2 },
974 .{ .movd, .mr, &.{ .rm32, .xmm }, &.{ 0x66, 0x0f, 0x7e }, 0, .none, .sse2 },
931975 .{ .movq, .mr, &.{ .rm64, .xmm }, &.{ 0x66, 0x0f, 0x7e }, 0, .long, .sse2 },
932976
977 .{ .movdqa, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x6f }, 0, .none, .sse2 },
978 .{ .movdqa, .mr, &.{ .xmm_m128, .xmm }, &.{ 0x66, 0x0f, 0x7f }, 0, .none, .sse2 },
979
980 .{ .movdqu, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0x6f }, 0, .none, .sse2 },
981 .{ .movdqu, .mr, &.{ .xmm_m128, .xmm }, &.{ 0xf3, 0x0f, 0x7f }, 0, .none, .sse2 },
982
933983 .{ .movq, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0x7e }, 0, .none, .sse2 },
934984 .{ .movq, .mr, &.{ .xmm_m64, .xmm }, &.{ 0x66, 0x0f, 0xd6 }, 0, .none, .sse2 },
935985
......@@ -942,10 +992,39 @@ pub const table = [_]Entry{
942992
943993 .{ .orpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x56 }, 0, .none, .sse2 },
944994
995 .{ .paddb, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xfc }, 0, .none, .sse2 },
996 .{ .paddw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xfd }, 0, .none, .sse2 },
997 .{ .paddd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xfe }, 0, .none, .sse2 },
998 .{ .paddq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd4 }, 0, .none, .sse2 },
999
1000 .{ .paddsb, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xec }, 0, .none, .sse2 },
1001 .{ .paddsw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xed }, 0, .none, .sse2 },
1002
1003 .{ .paddusb, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xdc }, 0, .none, .sse2 },
1004 .{ .paddusw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xdd }, 0, .none, .sse2 },
1005
1006 .{ .pand, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xdb }, 0, .none, .sse2 },
1007
1008 .{ .pandn, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xdf }, 0, .none, .sse2 },
1009
9451010 .{ .pextrw, .rmi, &.{ .r32, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0xc5 }, 0, .none, .sse2 },
9461011
9471012 .{ .pinsrw, .rmi, &.{ .xmm, .r32_m16, .imm8 }, &.{ 0x66, 0x0f, 0xc4 }, 0, .none, .sse2 },
9481013
1014 .{ .pmaxsw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xee }, 0, .none, .sse2 },
1015
1016 .{ .pmaxub, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xde }, 0, .none, .sse2 },
1017
1018 .{ .pminsw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xea }, 0, .none, .sse2 },
1019
1020 .{ .pminub, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xda }, 0, .none, .sse2 },
1021
1022 .{ .pmulhw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xe5 }, 0, .none, .sse2 },
1023
1024 .{ .pmullw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd5 }, 0, .none, .sse2 },
1025
1026 .{ .por, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xeb }, 0, .none, .sse2 },
1027
9491028 .{ .pshufhw, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0xf3, 0x0f, 0x70 }, 0, .none, .sse2 },
9501029
9511030 .{ .pshuflw, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0xf2, 0x0f, 0x70 }, 0, .none, .sse2 },
......@@ -957,6 +1036,18 @@ pub const table = [_]Entry{
9571036 .{ .psrlq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd3 }, 0, .none, .sse2 },
9581037 .{ .psrlq, .mi, &.{ .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x73 }, 2, .none, .sse2 },
9591038
1039 .{ .psubb, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xf8 }, 0, .none, .sse2 },
1040 .{ .psubw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xf9 }, 0, .none, .sse2 },
1041 .{ .psubd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xfa }, 0, .none, .sse2 },
1042
1043 .{ .psubsb, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xe8 }, 0, .none, .sse2 },
1044 .{ .psubsw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xe9 }, 0, .none, .sse2 },
1045
1046 .{ .psubq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xfb }, 0, .none, .sse2 },
1047
1048 .{ .psubusb, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd8 }, 0, .none, .sse2 },
1049 .{ .psubusw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd9 }, 0, .none, .sse2 },
1050
9601051 .{ .punpckhbw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x68 }, 0, .none, .sse2 },
9611052 .{ .punpckhwd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x69 }, 0, .none, .sse2 },
9621053 .{ .punpckhdq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x6a }, 0, .none, .sse2 },
......@@ -967,6 +1058,10 @@ pub const table = [_]Entry{
9671058 .{ .punpckldq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x62 }, 0, .none, .sse2 },
9681059 .{ .punpcklqdq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x6c }, 0, .none, .sse2 },
9691060
1061 .{ .pxor, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xef }, 0, .none, .sse2 },
1062
1063 .{ .shufpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0xc6 }, 0, .none, .sse2 },
1064
9701065 .{ .sqrtpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x51 }, 0, .none, .sse2 },
9711066
9721067 .{ .sqrtsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x51 }, 0, .none, .sse2 },
......@@ -990,6 +1085,10 @@ pub const table = [_]Entry{
9901085 .{ .movsldup, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0x12 }, 0, .none, .sse3 },
9911086
9921087 // SSE4.1
1088 .{ .extractps, .mri, &.{ .rm32, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x17 }, 0, .none, .sse4_1 },
1089
1090 .{ .insertps, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x21 }, 0, .none, .sse4_1 },
1091
9931092 .{ .pextrb, .mri, &.{ .r32_m8, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x14 }, 0, .none, .sse4_1 },
9941093 .{ .pextrd, .mri, &.{ .rm32, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x16 }, 0, .none, .sse4_1 },
9951094 .{ .pextrq, .mri, &.{ .rm64, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x16 }, 0, .long, .sse4_1 },
......@@ -1000,6 +1099,22 @@ pub const table = [_]Entry{
10001099 .{ .pinsrd, .rmi, &.{ .xmm, .rm32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x22 }, 0, .none, .sse4_1 },
10011100 .{ .pinsrq, .rmi, &.{ .xmm, .rm64, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x22 }, 0, .long, .sse4_1 },
10021101
1102 .{ .pmaxsb, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x3c }, 0, .none, .sse4_1 },
1103 .{ .pmaxsd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x3d }, 0, .none, .sse4_1 },
1104
1105 .{ .pmaxuw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x3e }, 0, .none, .sse4_1 },
1106
1107 .{ .pmaxud, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x3f }, 0, .none, .sse4_1 },
1108
1109 .{ .pminsb, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x38 }, 0, .none, .sse4_1 },
1110 .{ .pminsd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x39 }, 0, .none, .sse4_1 },
1111
1112 .{ .pminuw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x3a }, 0, .none, .sse4_1 },
1113
1114 .{ .pminud, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x3b }, 0, .none, .sse4_1 },
1115
1116 .{ .pmulld, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x40 }, 0, .none, .sse4_1 },
1117
10031118 .{ .roundpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x09 }, 0, .none, .sse4_1 },
10041119
10051120 .{ .roundps, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x08 }, 0, .none, .sse4_1 },
......@@ -1019,15 +1134,68 @@ pub const table = [_]Entry{
10191134
10201135 .{ .vaddss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x58 }, 0, .vex_lig_wig, .avx },
10211136
1137 .{ .vandnpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x55 }, 0, .vex_128_wig, .avx },
1138 .{ .vandnpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x55 }, 0, .vex_256_wig, .avx },
1139
1140 .{ .vandnps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x55 }, 0, .vex_128_wig, .avx },
1141 .{ .vandnps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x55 }, 0, .vex_256_wig, .avx },
1142
1143 .{ .vandpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x54 }, 0, .vex_128_wig, .avx },
1144 .{ .vandpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x54 }, 0, .vex_256_wig, .avx },
1145
1146 .{ .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 },
1148
1149 .{ .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 },
1151 .{ .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 },
1153
1154 .{ .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 },
1156
1157 .{ .vcvtdq2ps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5b }, 0, .vex_128_wig, .avx },
1158 .{ .vcvtdq2ps, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x0f, 0x5b }, 0, .vex_256_wig, .avx },
1159
1160 .{ .vcvtpd2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf2, 0x0f, 0xe6 }, 0, .vex_128_wig, .avx },
1161 .{ .vcvtpd2dq, .rm, &.{ .xmm, .ymm_m256 }, &.{ 0xf2, 0x0f, 0xe6 }, 0, .vex_256_wig, .avx },
1162
1163 .{ .vcvtpd2ps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5a }, 0, .vex_128_wig, .avx },
1164 .{ .vcvtpd2ps, .rm, &.{ .xmm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5a }, 0, .vex_256_wig, .avx },
1165
1166 .{ .vcvtps2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5b }, 0, .vex_128_wig, .avx },
1167 .{ .vcvtps2dq, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5b }, 0, .vex_256_wig, .avx },
1168
1169 .{ .vcvtps2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x0f, 0x5a }, 0, .vex_128_wig, .avx },
1170 .{ .vcvtps2pd, .rm, &.{ .ymm, .xmm_m128 }, &.{ 0x0f, 0x5a }, 0, .vex_256_wig, .avx },
1171
1172 .{ .vcvtsd2si, .rm, &.{ .r32, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2d }, 0, .vex_lig_w0, .sse2 },
1173 .{ .vcvtsd2si, .rm, &.{ .r64, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2d }, 0, .vex_lig_w1, .sse2 },
1174
10221175 .{ .vcvtsd2ss, .rvm, &.{ .xmm, .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .vex_lig_wig, .avx },
10231176
10241177 .{ .vcvtsi2sd, .rvm, &.{ .xmm, .xmm, .rm32 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w0, .avx },
10251178 .{ .vcvtsi2sd, .rvm, &.{ .xmm, .xmm, .rm64 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w1, .avx },
10261179
1027 .{ .vcvtsi2ss, .rvm, &.{ .xmm, .xmm, .rm32 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w0, .avx },
1028 .{ .vcvtsi2ss, .rvm, &.{ .xmm, .xmm, .rm64 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w1, .avx },
1180 .{ .vcvtsi2ss, .rvm, &.{ .xmm, .xmm, .rm32 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .vex_lig_w0, .avx },
1181 .{ .vcvtsi2ss, .rvm, &.{ .xmm, .xmm, .rm64 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .vex_lig_w1, .avx },
1182
1183 .{ .vcvtss2sd, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5a }, 0, .vex_lig_wig, .avx },
1184
1185 .{ .vcvtss2si, .rm, &.{ .r32, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2d }, 0, .vex_lig_w0, .avx },
1186 .{ .vcvtss2si, .rm, &.{ .r64, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2d }, 0, .vex_lig_w1, .avx },
1187
1188 .{ .vcvttpd2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xe6 }, 0, .vex_128_wig, .avx },
1189 .{ .vcvttpd2dq, .rm, &.{ .xmm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xe6 }, 0, .vex_256_wig, .avx },
10291190
1030 .{ .vcvtss2sd, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .vex_lig_wig, .avx },
1191 .{ .vcvttps2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0x5b }, 0, .vex_128_wig, .avx },
1192 .{ .vcvttps2dq, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0xf3, 0x0f, 0x5b }, 0, .vex_256_wig, .avx },
1193
1194 .{ .vcvttsd2si, .rm, &.{ .r32, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2c }, 0, .vex_lig_w0, .sse2 },
1195 .{ .vcvttsd2si, .rm, &.{ .r64, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2c }, 0, .vex_lig_w1, .sse2 },
1196
1197 .{ .vcvttss2si, .rm, &.{ .r32, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2c }, 0, .vex_lig_w0, .avx },
1198 .{ .vcvttss2si, .rm, &.{ .r64, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2c }, 0, .vex_lig_w1, .avx },
10311199
10321200 .{ .vdivpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5e }, 0, .vex_128_wig, .avx },
10331201 .{ .vdivpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5e }, 0, .vex_256_wig, .avx },
......@@ -1039,6 +1207,14 @@ pub const table = [_]Entry{
10391207
10401208 .{ .vdivss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5e }, 0, .vex_lig_wig, .avx },
10411209
1210 .{ .vextractf128, .mri, &.{ .xmm_m128, .ymm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x19 }, 0, .vex_256_w0, .avx },
1211
1212 .{ .vextractps, .mri, &.{ .rm32, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x17 }, 0, .vex_128_wig, .avx },
1213
1214 .{ .vinsertf128, .rvmi, &.{ .ymm, .ymm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x18 }, 0, .vex_256_w0, .avx },
1215
1216 .{ .vinsertps, .rvmi, &.{ .xmm, .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x21 }, 0, .vex_128_wig, .avx },
1217
10421218 .{ .vmaxpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5f }, 0, .vex_128_wig, .avx },
10431219 .{ .vmaxpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5f }, 0, .vex_256_wig, .avx },
10441220
......@@ -1069,11 +1245,31 @@ pub const table = [_]Entry{
10691245 .{ .vmovaps, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x0f, 0x28 }, 0, .vex_256_wig, .avx },
10701246 .{ .vmovaps, .mr, &.{ .ymm_m256, .ymm }, &.{ 0x0f, 0x29 }, 0, .vex_256_wig, .avx },
10711247
1248 .{ .vmovd, .rm, &.{ .xmm, .rm32 }, &.{ 0x66, 0x0f, 0x6e }, 0, .vex_128_w0, .avx },
1249 .{ .vmovq, .rm, &.{ .xmm, .rm64 }, &.{ 0x66, 0x0f, 0x6e }, 0, .vex_128_w1, .avx },
1250 .{ .vmovd, .mr, &.{ .rm32, .xmm }, &.{ 0x66, 0x0f, 0x7e }, 0, .vex_128_w0, .avx },
1251 .{ .vmovq, .mr, &.{ .rm64, .xmm }, &.{ 0x66, 0x0f, 0x7e }, 0, .vex_128_w1, .avx },
1252
10721253 .{ .vmovddup, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x12 }, 0, .vex_128_wig, .avx },
10731254 .{ .vmovddup, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0xf2, 0x0f, 0x12 }, 0, .vex_256_wig, .avx },
10741255
1256 .{ .vmovdqa, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x6f }, 0, .vex_128_wig, .avx },
1257 .{ .vmovdqa, .mr, &.{ .xmm_m128, .xmm }, &.{ 0x66, 0x0f, 0x7f }, 0, .vex_128_wig, .avx },
1258 .{ .vmovdqa, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x6f }, 0, .vex_256_wig, .avx },
1259 .{ .vmovdqa, .mr, &.{ .ymm_m256, .ymm }, &.{ 0x66, 0x0f, 0x7f }, 0, .vex_256_wig, .avx },
1260
1261 .{ .vmovdqu, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0x6f }, 0, .vex_128_wig, .avx },
1262 .{ .vmovdqu, .mr, &.{ .xmm_m128, .xmm }, &.{ 0xf3, 0x0f, 0x7f }, 0, .vex_128_wig, .avx },
1263 .{ .vmovdqu, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0xf3, 0x0f, 0x6f }, 0, .vex_256_wig, .avx },
1264 .{ .vmovdqu, .mr, &.{ .ymm_m256, .ymm }, &.{ 0xf3, 0x0f, 0x7f }, 0, .vex_256_wig, .avx },
1265
10751266 .{ .vmovhlps, .rvm, &.{ .xmm, .xmm, .xmm }, &.{ 0x0f, 0x12 }, 0, .vex_128_wig, .avx },
10761267
1268 .{ .vmovlhps, .rvm, &.{ .xmm, .xmm, .xmm }, &.{ 0x0f, 0x16 }, 0, .vex_128_wig, .avx },
1269
1270 .{ .vmovq, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0x7e }, 0, .vex_128_wig, .avx },
1271 .{ .vmovq, .mr, &.{ .xmm_m64, .xmm }, &.{ 0x66, 0x0f, 0xd6 }, 0, .vex_128_wig, .avx },
1272
10771273 .{ .vmovsd, .rvm, &.{ .xmm, .xmm, .xmm }, &.{ 0xf2, 0x0f, 0x10 }, 0, .vex_lig_wig, .avx },
10781274 .{ .vmovsd, .rm, &.{ .xmm, .m64 }, &.{ 0xf2, 0x0f, 0x10 }, 0, .vex_lig_wig, .avx },
10791275 .{ .vmovsd, .mvr, &.{ .xmm, .xmm, .xmm }, &.{ 0xf2, 0x0f, 0x11 }, 0, .vex_lig_wig, .avx },
......@@ -1110,6 +1306,27 @@ pub const table = [_]Entry{
11101306
11111307 .{ .vmulss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x59 }, 0, .vex_lig_wig, .avx },
11121308
1309 .{ .vorpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x56 }, 0, .vex_128_wig, .avx },
1310 .{ .vorpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x56 }, 0, .vex_256_wig, .avx },
1311
1312 .{ .vorps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x56 }, 0, .vex_128_wig, .avx },
1313 .{ .vorps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x56 }, 0, .vex_256_wig, .avx },
1314
1315 .{ .vpaddb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xfc }, 0, .vex_128_wig, .avx },
1316 .{ .vpaddw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xfd }, 0, .vex_128_wig, .avx },
1317 .{ .vpaddd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xfe }, 0, .vex_128_wig, .avx },
1318 .{ .vpaddq, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd4 }, 0, .vex_128_wig, .avx },
1319
1320 .{ .vpaddsb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xec }, 0, .vex_128_wig, .avx },
1321 .{ .vpaddsw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xed }, 0, .vex_128_wig, .avx },
1322
1323 .{ .vpaddusb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xdc }, 0, .vex_128_wig, .avx },
1324 .{ .vpaddusw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xdd }, 0, .vex_128_wig, .avx },
1325
1326 .{ .vpand, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xdb }, 0, .vex_128_wig, .avx },
1327
1328 .{ .vpandn, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xdf }, 0, .vex_128_wig, .avx },
1329
11131330 .{ .vpextrb, .mri, &.{ .r32_m8, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x14 }, 0, .vex_128_w0, .avx },
11141331 .{ .vpextrd, .mri, &.{ .rm32, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x16 }, 0, .vex_128_w0, .avx },
11151332 .{ .vpextrq, .mri, &.{ .rm64, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x16 }, 0, .vex_128_w1, .avx },
......@@ -1123,6 +1340,32 @@ pub const table = [_]Entry{
11231340
11241341 .{ .vpinsrw, .rvmi, &.{ .xmm, .xmm, .r32_m16, .imm8 }, &.{ 0x66, 0x0f, 0xc4 }, 0, .vex_128_wig, .avx },
11251342
1343 .{ .vpmaxsb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x3c }, 0, .vex_128_wig, .avx },
1344 .{ .vpmaxsw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xee }, 0, .vex_128_wig, .avx },
1345 .{ .vpmaxsd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x3d }, 0, .vex_128_wig, .avx },
1346
1347 .{ .vpmaxub, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xde }, 0, .vex_128_wig, .avx },
1348 .{ .vpmaxuw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x3e }, 0, .vex_128_wig, .avx },
1349
1350 .{ .vpmaxud, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x3f }, 0, .vex_128_wig, .avx },
1351
1352 .{ .vpminsb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x38 }, 0, .vex_128_wig, .avx },
1353 .{ .vpminsw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xea }, 0, .vex_128_wig, .avx },
1354 .{ .vpminsd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x39 }, 0, .vex_128_wig, .avx },
1355
1356 .{ .vpminub, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xda }, 0, .vex_128_wig, .avx },
1357 .{ .vpminuw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x3a }, 0, .vex_128_wig, .avx },
1358
1359 .{ .vpminud, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x3b }, 0, .vex_128_wig, .avx },
1360
1361 .{ .vpmulhw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xe5 }, 0, .vex_128_wig, .avx },
1362
1363 .{ .vpmulld, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x40 }, 0, .vex_128_wig, .avx },
1364
1365 .{ .vpmullw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd5 }, 0, .vex_128_wig, .avx },
1366
1367 .{ .vpor, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xeb }, 0, .vex_128_wig, .avx },
1368
11261369 .{ .vpsrlw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd1 }, 0, .vex_128_wig, .avx },
11271370 .{ .vpsrlw, .vmi, &.{ .xmm, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x71 }, 2, .vex_128_wig, .avx },
11281371 .{ .vpsrld, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd2 }, 0, .vex_128_wig, .avx },
......@@ -1130,6 +1373,18 @@ pub const table = [_]Entry{
11301373 .{ .vpsrlq, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd3 }, 0, .vex_128_wig, .avx },
11311374 .{ .vpsrlq, .vmi, &.{ .xmm, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x73 }, 2, .vex_128_wig, .avx },
11321375
1376 .{ .vpsubb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xf8 }, 0, .vex_128_wig, .avx },
1377 .{ .vpsubw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xf9 }, 0, .vex_128_wig, .avx },
1378 .{ .vpsubd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xfa }, 0, .vex_128_wig, .avx },
1379
1380 .{ .vpsubsb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xe8 }, 0, .vex_128_wig, .avx },
1381 .{ .vpsubsw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xe9 }, 0, .vex_128_wig, .avx },
1382
1383 .{ .vpsubq, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xfb }, 0, .vex_128_wig, .avx },
1384
1385 .{ .vpsubusb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd8 }, 0, .vex_128_wig, .avx },
1386 .{ .vpsubusw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd9 }, 0, .vex_128_wig, .avx },
1387
11331388 .{ .vpunpckhbw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x68 }, 0, .vex_128_wig, .avx },
11341389 .{ .vpunpckhwd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x69 }, 0, .vex_128_wig, .avx },
11351390 .{ .vpunpckhdq, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x6a }, 0, .vex_128_wig, .avx },
......@@ -1140,6 +1395,8 @@ pub const table = [_]Entry{
11401395 .{ .vpunpckldq, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x62 }, 0, .vex_128_wig, .avx },
11411396 .{ .vpunpcklqdq, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x6c }, 0, .vex_128_wig, .avx },
11421397
1398 .{ .vpxor, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xef }, 0, .vex_128_wig, .avx },
1399
11431400 .{ .vroundpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x09 }, 0, .vex_128_wig, .avx },
11441401 .{ .vroundpd, .rmi, &.{ .ymm, .ymm_m256, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x09 }, 0, .vex_256_wig, .avx },
11451402
......@@ -1150,6 +1407,12 @@ pub const table = [_]Entry{
11501407
11511408 .{ .vroundss, .rvmi, &.{ .xmm, .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0a }, 0, .vex_lig_wig, .avx },
11521409
1410 .{ .vshufpd, .rvmi, &.{ .xmm, .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0xc6 }, 0, .vex_128_wig, .avx },
1411 .{ .vshufpd, .rvmi, &.{ .ymm, .ymm, .ymm_m256, .imm8 }, &.{ 0x66, 0x0f, 0xc6 }, 0, .vex_256_wig, .avx },
1412
1413 .{ .vshufps, .rvmi, &.{ .xmm, .xmm, .xmm_m128, .imm8 }, &.{ 0x0f, 0xc6 }, 0, .vex_128_wig, .avx },
1414 .{ .vshufps, .rvmi, &.{ .ymm, .ymm, .ymm_m256, .imm8 }, &.{ 0x0f, 0xc6 }, 0, .vex_256_wig, .avx },
1415
11531416 .{ .vsqrtpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x51 }, 0, .vex_128_wig, .avx },
11541417 .{ .vsqrtpd, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x51 }, 0, .vex_256_wig, .avx },
11551418
......@@ -1170,6 +1433,12 @@ pub const table = [_]Entry{
11701433
11711434 .{ .vsubss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .vex_lig_wig, .avx },
11721435
1436 .{ .vxorpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x57 }, 0, .vex_128_wig, .avx },
1437 .{ .vxorpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x57 }, 0, .vex_256_wig, .avx },
1438
1439 .{ .vxorps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x57 }, 0, .vex_128_wig, .avx },
1440 .{ .vxorps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x57 }, 0, .vex_256_wig, .avx },
1441
11731442 // F16C
11741443 .{ .vcvtph2ps, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x66, 0x0f, 0x38, 0x13 }, 0, .vex_128_w0, .f16c },
11751444 .{ .vcvtph2ps, .rm, &.{ .ymm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x13 }, 0, .vex_256_w0, .f16c },
......@@ -1201,6 +1470,51 @@ pub const table = [_]Entry{
12011470 .{ .vfmadd231ss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0x66, 0x0f, 0x38, 0xb9 }, 0, .vex_lig_w0, .fma },
12021471
12031472 // AVX2
1473 .{ .vbroadcastss, .rm, &.{ .xmm, .xmm }, &.{ 0x66, 0x0f, 0x38, 0x18 }, 0, .vex_128_w0, .avx2 },
1474 .{ .vbroadcastss, .rm, &.{ .ymm, .xmm }, &.{ 0x66, 0x0f, 0x38, 0x18 }, 0, .vex_256_w0, .avx2 },
1475 .{ .vbroadcastsd, .rm, &.{ .ymm, .xmm }, &.{ 0x66, 0x0f, 0x38, 0x19 }, 0, .vex_256_w0, .avx2 },
1476
1477 .{ .vpaddb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xfc }, 0, .vex_256_wig, .avx2 },
1478 .{ .vpaddw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xfd }, 0, .vex_256_wig, .avx2 },
1479 .{ .vpaddd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xfe }, 0, .vex_256_wig, .avx2 },
1480 .{ .vpaddq, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xd4 }, 0, .vex_256_wig, .avx2 },
1481
1482 .{ .vpaddsb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xec }, 0, .vex_256_wig, .avx2 },
1483 .{ .vpaddsw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xed }, 0, .vex_256_wig, .avx2 },
1484
1485 .{ .vpaddusb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xdc }, 0, .vex_256_wig, .avx2 },
1486 .{ .vpaddusw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xdd }, 0, .vex_256_wig, .avx2 },
1487
1488 .{ .vpand, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xdb }, 0, .vex_256_wig, .avx2 },
1489
1490 .{ .vpandn, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xdf }, 0, .vex_256_wig, .avx2 },
1491
1492 .{ .vpmaxsb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x3c }, 0, .vex_256_wig, .avx },
1493 .{ .vpmaxsw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xee }, 0, .vex_256_wig, .avx },
1494 .{ .vpmaxsd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x3d }, 0, .vex_256_wig, .avx },
1495
1496 .{ .vpmaxub, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xde }, 0, .vex_256_wig, .avx },
1497 .{ .vpmaxuw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x3e }, 0, .vex_256_wig, .avx },
1498
1499 .{ .vpmaxud, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x3f }, 0, .vex_256_wig, .avx },
1500
1501 .{ .vpminsb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x38 }, 0, .vex_256_wig, .avx },
1502 .{ .vpminsw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xea }, 0, .vex_256_wig, .avx },
1503 .{ .vpminsd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x39 }, 0, .vex_256_wig, .avx },
1504
1505 .{ .vpminub, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xda }, 0, .vex_256_wig, .avx },
1506 .{ .vpminuw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x3a }, 0, .vex_256_wig, .avx },
1507
1508 .{ .vpminud, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x3b }, 0, .vex_256_wig, .avx },
1509
1510 .{ .vpmulhw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xe5 }, 0, .vex_256_wig, .avx },
1511
1512 .{ .vpmulld, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x40 }, 0, .vex_256_wig, .avx },
1513
1514 .{ .vpmullw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xd5 }, 0, .vex_256_wig, .avx },
1515
1516 .{ .vpor, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xeb }, 0, .vex_256_wig, .avx2 },
1517
12041518 .{ .vpsrlw, .rvm, &.{ .ymm, .ymm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd1 }, 0, .vex_256_wig, .avx2 },
12051519 .{ .vpsrlw, .vmi, &.{ .ymm, .ymm, .imm8 }, &.{ 0x66, 0x0f, 0x71 }, 2, .vex_256_wig, .avx2 },
12061520 .{ .vpsrld, .rvm, &.{ .ymm, .ymm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd2 }, 0, .vex_256_wig, .avx2 },
......@@ -1208,6 +1522,18 @@ pub const table = [_]Entry{
12081522 .{ .vpsrlq, .rvm, &.{ .ymm, .ymm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd3 }, 0, .vex_256_wig, .avx2 },
12091523 .{ .vpsrlq, .vmi, &.{ .ymm, .ymm, .imm8 }, &.{ 0x66, 0x0f, 0x73 }, 2, .vex_256_wig, .avx2 },
12101524
1525 .{ .vpsubb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xf8 }, 0, .vex_256_wig, .avx2 },
1526 .{ .vpsubw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xf9 }, 0, .vex_256_wig, .avx2 },
1527 .{ .vpsubd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xfa }, 0, .vex_256_wig, .avx2 },
1528
1529 .{ .vpsubsb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xe8 }, 0, .vex_256_wig, .avx2 },
1530 .{ .vpsubsw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xe9 }, 0, .vex_256_wig, .avx2 },
1531
1532 .{ .vpsubq, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xfb }, 0, .vex_256_wig, .avx2 },
1533
1534 .{ .vpsubusb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xd8 }, 0, .vex_256_wig, .avx2 },
1535 .{ .vpsubusw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xd9 }, 0, .vex_256_wig, .avx2 },
1536
12111537 .{ .vpunpckhbw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x68 }, 0, .vex_256_wig, .avx2 },
12121538 .{ .vpunpckhwd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x69 }, 0, .vex_256_wig, .avx2 },
12131539 .{ .vpunpckhdq, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x6a }, 0, .vex_256_wig, .avx2 },
......@@ -1217,5 +1543,7 @@ pub const table = [_]Entry{
12171543 .{ .vpunpcklwd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x61 }, 0, .vex_256_wig, .avx2 },
12181544 .{ .vpunpckldq, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x62 }, 0, .vex_256_wig, .avx2 },
12191545 .{ .vpunpcklqdq, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x6c }, 0, .vex_256_wig, .avx2 },
1546
1547 .{ .vpxor, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xef }, 0, .vex_256_wig, .avx2 },
12201548};
12211549// zig fmt: on
src/codegen.zig+39-9
......@@ -380,7 +380,7 @@ pub fn generateSymbol(
380380
381381 return Result.ok;
382382 },
383 .field_ptr, .elem_ptr => return lowerParentPtr(
383 .field_ptr, .elem_ptr, .opt_payload_ptr => return lowerParentPtr(
384384 bin_file,
385385 src_loc,
386386 typed_value,
......@@ -812,7 +812,6 @@ fn lowerParentPtr(
812812 reloc_info: RelocInfo,
813813) CodeGenError!Result {
814814 const target = bin_file.options.target;
815
816815 switch (parent_ptr.tag()) {
817816 .field_ptr => {
818817 const field_ptr = parent_ptr.castTag(.field_ptr).?.data;
......@@ -858,6 +857,31 @@ fn lowerParentPtr(
858857 reloc_info.offset(@intCast(u32, elem_ptr.index * elem_ptr.elem_ty.abiSize(target))),
859858 );
860859 },
860 .opt_payload_ptr => {
861 const opt_payload_ptr = parent_ptr.castTag(.opt_payload_ptr).?.data;
862 return lowerParentPtr(
863 bin_file,
864 src_loc,
865 typed_value,
866 opt_payload_ptr.container_ptr,
867 code,
868 debug_output,
869 reloc_info,
870 );
871 },
872 .eu_payload_ptr => {
873 const eu_payload_ptr = parent_ptr.castTag(.eu_payload_ptr).?.data;
874 const pl_ty = eu_payload_ptr.container_ty.errorUnionPayload();
875 return lowerParentPtr(
876 bin_file,
877 src_loc,
878 typed_value,
879 eu_payload_ptr.container_ptr,
880 code,
881 debug_output,
882 reloc_info.offset(@intCast(u32, errUnionPayloadOffset(pl_ty, target))),
883 );
884 },
861885 .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef(
862886 bin_file,
863887 src_loc,
......@@ -1189,12 +1213,16 @@ pub fn genTypedValue(
11891213 .enum_simple => {
11901214 return GenResult.mcv(.{ .immediate = field_index.data });
11911215 },
1192 .enum_full, .enum_nonexhaustive => {
1193 const enum_full = typed_value.ty.cast(Type.Payload.EnumFull).?.data;
1194 if (enum_full.values.count() != 0) {
1195 const tag_val = enum_full.values.keys()[field_index.data];
1216 .enum_numbered, .enum_full, .enum_nonexhaustive => {
1217 const enum_values = if (typed_value.ty.castTag(.enum_numbered)) |pl|
1218 pl.data.values
1219 else
1220 typed_value.ty.cast(Type.Payload.EnumFull).?.data.values;
1221 if (enum_values.count() != 0) {
1222 const tag_val = enum_values.keys()[field_index.data];
1223 var buf: Type.Payload.Bits = undefined;
11961224 return genTypedValue(bin_file, src_loc, .{
1197 .ty = enum_full.tag_ty,
1225 .ty = typed_value.ty.intTagType(&buf),
11981226 .val = tag_val,
11991227 }, owner_decl_index);
12001228 } else {
......@@ -1258,9 +1286,10 @@ pub fn genTypedValue(
12581286}
12591287
12601288pub fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u64 {
1289 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return 0;
12611290 const payload_align = payload_ty.abiAlignment(target);
12621291 const error_align = Type.anyerror.abiAlignment(target);
1263 if (payload_align >= error_align) {
1292 if (payload_align >= error_align or !payload_ty.hasRuntimeBitsIgnoreComptime()) {
12641293 return 0;
12651294 } else {
12661295 return mem.alignForwardGeneric(u64, Type.anyerror.abiSize(target), payload_align);
......@@ -1268,9 +1297,10 @@ pub fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u64 {
12681297}
12691298
12701299pub fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u64 {
1300 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return 0;
12711301 const payload_align = payload_ty.abiAlignment(target);
12721302 const error_align = Type.anyerror.abiAlignment(target);
1273 if (payload_align >= error_align) {
1303 if (payload_align >= error_align and payload_ty.hasRuntimeBitsIgnoreComptime()) {
12741304 return mem.alignForwardGeneric(u64, payload_ty.abiSize(target), error_align);
12751305 } else {
12761306 return 0;
src/link/Dwarf.zig+115-71
......@@ -184,12 +184,14 @@ pub const DeclState = struct {
184184 try dbg_info_buffer.append(@enumToInt(AbbrevKind.pad1));
185185 },
186186 .Bool => {
187 try dbg_info_buffer.appendSlice(&[_]u8{
188 @enumToInt(AbbrevKind.base_type),
189 DW.ATE.boolean, // DW.AT.encoding , DW.FORM.data1
190 1, // DW.AT.byte_size, DW.FORM.data1
191 'b', 'o', 'o', 'l', 0, // DW.AT.name, DW.FORM.string
192 });
187 try dbg_info_buffer.ensureUnusedCapacity(12);
188 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type));
189 // DW.AT.encoding, DW.FORM.data1
190 dbg_info_buffer.appendAssumeCapacity(DW.ATE.boolean);
191 // DW.AT.byte_size, DW.FORM.udata
192 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target));
193 // DW.AT.name, DW.FORM.string
194 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)});
193195 },
194196 .Int => {
195197 const info = ty.intInfo(target);
......@@ -200,9 +202,9 @@ pub const DeclState = struct {
200202 .signed => DW.ATE.signed,
201203 .unsigned => DW.ATE.unsigned,
202204 });
203 // DW.AT.byte_size, DW.FORM.data1
204 dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(target)));
205 // DW.AT.name, DW.FORM.string
205 // DW.AT.byte_size, DW.FORM.udata
206 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target));
207 // DW.AT.name, DW.FORM.string
206208 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)});
207209 },
208210 .Optional => {
......@@ -211,9 +213,9 @@ pub const DeclState = struct {
211213 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type));
212214 // DW.AT.encoding, DW.FORM.data1
213215 dbg_info_buffer.appendAssumeCapacity(DW.ATE.address);
214 // DW.AT.byte_size, DW.FORM.data1
215 dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(target)));
216 // DW.AT.name, DW.FORM.string
216 // DW.AT.byte_size, DW.FORM.udata
217 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target));
218 // DW.AT.name, DW.FORM.string
217219 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)});
218220 } else {
219221 // Non-pointer optionals are structs: struct { .maybe = *, .val = * }
......@@ -221,7 +223,7 @@ pub const DeclState = struct {
221223 const payload_ty = ty.optionalChild(buf);
222224 // DW.AT.structure_type
223225 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
224 // DW.AT.byte_size, DW.FORM.sdata
226 // DW.AT.byte_size, DW.FORM.udata
225227 const abi_size = ty.abiSize(target);
226228 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
227229 // DW.AT.name, DW.FORM.string
......@@ -236,7 +238,7 @@ pub const DeclState = struct {
236238 var index = dbg_info_buffer.items.len;
237239 try dbg_info_buffer.resize(index + 4);
238240 try self.addTypeRelocGlobal(atom_index, Type.bool, @intCast(u32, index));
239 // DW.AT.data_member_location, DW.FORM.sdata
241 // DW.AT.data_member_location, DW.FORM.udata
240242 try dbg_info_buffer.ensureUnusedCapacity(6);
241243 dbg_info_buffer.appendAssumeCapacity(0);
242244 // DW.AT.member
......@@ -248,7 +250,7 @@ pub const DeclState = struct {
248250 index = dbg_info_buffer.items.len;
249251 try dbg_info_buffer.resize(index + 4);
250252 try self.addTypeRelocGlobal(atom_index, payload_ty, @intCast(u32, index));
251 // DW.AT.data_member_location, DW.FORM.sdata
253 // DW.AT.data_member_location, DW.FORM.udata
252254 const offset = abi_size - payload_ty.abiSize(target);
253255 try leb128.writeULEB128(dbg_info_buffer.writer(), offset);
254256 // DW.AT.structure_type delimit children
......@@ -263,8 +265,8 @@ pub const DeclState = struct {
263265 // DW.AT.structure_type
264266 try dbg_info_buffer.ensureUnusedCapacity(2);
265267 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_type));
266 // DW.AT.byte_size, DW.FORM.sdata
267 dbg_info_buffer.appendAssumeCapacity(ptr_bytes * 2);
268 // DW.AT.byte_size, DW.FORM.udata
269 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target));
268270 // DW.AT.name, DW.FORM.string
269271 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)});
270272 // DW.AT.member
......@@ -279,7 +281,7 @@ pub const DeclState = struct {
279281 var buf = try arena.create(Type.SlicePtrFieldTypeBuffer);
280282 const ptr_ty = ty.slicePtrFieldType(buf);
281283 try self.addTypeRelocGlobal(atom_index, ptr_ty, @intCast(u32, index));
282 // DW.AT.data_member_location, DW.FORM.sdata
284 // DW.AT.data_member_location, DW.FORM.udata
283285 try dbg_info_buffer.ensureUnusedCapacity(6);
284286 dbg_info_buffer.appendAssumeCapacity(0);
285287 // DW.AT.member
......@@ -291,7 +293,7 @@ pub const DeclState = struct {
291293 index = dbg_info_buffer.items.len;
292294 try dbg_info_buffer.resize(index + 4);
293295 try self.addTypeRelocGlobal(atom_index, Type.usize, @intCast(u32, index));
294 // DW.AT.data_member_location, DW.FORM.sdata
296 // DW.AT.data_member_location, DW.FORM.udata
295297 try dbg_info_buffer.ensureUnusedCapacity(2);
296298 dbg_info_buffer.appendAssumeCapacity(ptr_bytes);
297299 // DW.AT.structure_type delimit children
......@@ -329,9 +331,8 @@ pub const DeclState = struct {
329331 .Struct => blk: {
330332 // DW.AT.structure_type
331333 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
332 // DW.AT.byte_size, DW.FORM.sdata
333 const abi_size = ty.abiSize(target);
334 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
334 // DW.AT.byte_size, DW.FORM.udata
335 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target));
335336
336337 switch (ty.tag()) {
337338 .tuple, .anon_struct => {
......@@ -348,7 +349,7 @@ pub const DeclState = struct {
348349 var index = dbg_info_buffer.items.len;
349350 try dbg_info_buffer.resize(index + 4);
350351 try self.addTypeRelocGlobal(atom_index, field, @intCast(u32, index));
351 // DW.AT.data_member_location, DW.FORM.sdata
352 // DW.AT.data_member_location, DW.FORM.udata
352353 const field_off = ty.structFieldOffset(field_index, target);
353354 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
354355 }
......@@ -380,7 +381,7 @@ pub const DeclState = struct {
380381 var index = dbg_info_buffer.items.len;
381382 try dbg_info_buffer.resize(index + 4);
382383 try self.addTypeRelocGlobal(atom_index, field.ty, @intCast(u32, index));
383 // DW.AT.data_member_location, DW.FORM.sdata
384 // DW.AT.data_member_location, DW.FORM.udata
384385 const field_off = ty.structFieldOffset(field_index, target);
385386 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
386387 }
......@@ -393,9 +394,8 @@ pub const DeclState = struct {
393394 .Enum => {
394395 // DW.AT.enumeration_type
395396 try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type));
396 // DW.AT.byte_size, DW.FORM.sdata
397 const abi_size = ty.abiSize(target);
398 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
397 // DW.AT.byte_size, DW.FORM.udata
398 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target));
399399 // DW.AT.name, DW.FORM.string
400400 const enum_name = try ty.nameAllocArena(arena, module);
401401 try dbg_info_buffer.ensureUnusedCapacity(enum_name.len + 1);
......@@ -446,7 +446,7 @@ pub const DeclState = struct {
446446 if (is_tagged) {
447447 // DW.AT.structure_type
448448 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
449 // DW.AT.byte_size, DW.FORM.sdata
449 // DW.AT.byte_size, DW.FORM.udata
450450 try leb128.writeULEB128(dbg_info_buffer.writer(), layout.abi_size);
451451 // DW.AT.name, DW.FORM.string
452452 try dbg_info_buffer.ensureUnusedCapacity(union_name.len + 1);
......@@ -463,13 +463,13 @@ pub const DeclState = struct {
463463 const inner_union_index = dbg_info_buffer.items.len;
464464 try dbg_info_buffer.resize(inner_union_index + 4);
465465 try self.addTypeRelocLocal(atom_index, @intCast(u32, inner_union_index), 5);
466 // DW.AT.data_member_location, DW.FORM.sdata
466 // DW.AT.data_member_location, DW.FORM.udata
467467 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset);
468468 }
469469
470470 // DW.AT.union_type
471471 try dbg_info_buffer.append(@enumToInt(AbbrevKind.union_type));
472 // DW.AT.byte_size, DW.FORM.sdata,
472 // DW.AT.byte_size, DW.FORM.udata,
473473 try leb128.writeULEB128(dbg_info_buffer.writer(), layout.payload_size);
474474 // DW.AT.name, DW.FORM.string
475475 if (is_tagged) {
......@@ -490,7 +490,7 @@ pub const DeclState = struct {
490490 const index = dbg_info_buffer.items.len;
491491 try dbg_info_buffer.resize(index + 4);
492492 try self.addTypeRelocGlobal(atom_index, field.ty, @intCast(u32, index));
493 // DW.AT.data_member_location, DW.FORM.sdata
493 // DW.AT.data_member_location, DW.FORM.udata
494494 try dbg_info_buffer.append(0);
495495 }
496496 // DW.AT.union_type delimit children
......@@ -507,7 +507,7 @@ pub const DeclState = struct {
507507 const index = dbg_info_buffer.items.len;
508508 try dbg_info_buffer.resize(index + 4);
509509 try self.addTypeRelocGlobal(atom_index, union_obj.tag_ty, @intCast(u32, index));
510 // DW.AT.data_member_location, DW.FORM.sdata
510 // DW.AT.data_member_location, DW.FORM.udata
511511 try leb128.writeULEB128(dbg_info_buffer.writer(), tag_offset);
512512
513513 // DW.AT.structure_type delimit children
......@@ -534,7 +534,7 @@ pub const DeclState = struct {
534534
535535 // DW.AT.structure_type
536536 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
537 // DW.AT.byte_size, DW.FORM.sdata
537 // DW.AT.byte_size, DW.FORM.udata
538538 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
539539 // DW.AT.name, DW.FORM.string
540540 const name = try ty.nameAllocArena(arena, module);
......@@ -551,7 +551,7 @@ pub const DeclState = struct {
551551 const index = dbg_info_buffer.items.len;
552552 try dbg_info_buffer.resize(index + 4);
553553 try self.addTypeRelocGlobal(atom_index, payload_ty, @intCast(u32, index));
554 // DW.AT.data_member_location, DW.FORM.sdata
554 // DW.AT.data_member_location, DW.FORM.udata
555555 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_off);
556556 }
557557
......@@ -566,7 +566,7 @@ pub const DeclState = struct {
566566 const index = dbg_info_buffer.items.len;
567567 try dbg_info_buffer.resize(index + 4);
568568 try self.addTypeRelocGlobal(atom_index, error_ty, @intCast(u32, index));
569 // DW.AT.data_member_location, DW.FORM.sdata
569 // DW.AT.data_member_location, DW.FORM.udata
570570 try leb128.writeULEB128(dbg_info_buffer.writer(), error_off);
571571 }
572572
......@@ -608,23 +608,44 @@ pub const DeclState = struct {
608608
609609 switch (loc) {
610610 .register => |reg| {
611 try dbg_info.ensureUnusedCapacity(3);
611 try dbg_info.ensureUnusedCapacity(4);
612612 dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));
613 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
614 1, // ULEB128 dwarf expression length
615 reg,
616 });
613 // DW.AT.location, DW.FORM.exprloc
614 var expr_len = std.io.countingWriter(std.io.null_writer);
615 if (reg < 32) {
616 expr_len.writer().writeByte(DW.OP.reg0 + reg) catch unreachable;
617 } else {
618 expr_len.writer().writeByte(DW.OP.regx) catch unreachable;
619 leb128.writeULEB128(expr_len.writer(), reg) catch unreachable;
620 }
621 leb128.writeULEB128(dbg_info.writer(), expr_len.bytes_written) catch unreachable;
622 if (reg < 32) {
623 dbg_info.appendAssumeCapacity(DW.OP.reg0 + reg);
624 } else {
625 dbg_info.appendAssumeCapacity(DW.OP.regx);
626 leb128.writeULEB128(dbg_info.writer(), reg) catch unreachable;
627 }
617628 },
618629 .stack => |info| {
619 try dbg_info.ensureUnusedCapacity(8);
630 try dbg_info.ensureUnusedCapacity(9);
620631 dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));
621 const fixup = dbg_info.items.len;
622 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
623 1, // we will backpatch it after we encode the displacement in LEB128
624 info.fp_register, // frame pointer
625 });
632 // DW.AT.location, DW.FORM.exprloc
633 var expr_len = std.io.countingWriter(std.io.null_writer);
634 if (info.fp_register < 32) {
635 expr_len.writer().writeByte(DW.OP.breg0 + info.fp_register) catch unreachable;
636 } else {
637 expr_len.writer().writeByte(DW.OP.bregx) catch unreachable;
638 leb128.writeULEB128(expr_len.writer(), info.fp_register) catch unreachable;
639 }
640 leb128.writeILEB128(expr_len.writer(), info.offset) catch unreachable;
641 leb128.writeULEB128(dbg_info.writer(), expr_len.bytes_written) catch unreachable;
642 if (info.fp_register < 32) {
643 dbg_info.appendAssumeCapacity(DW.OP.breg0 + info.fp_register);
644 } else {
645 dbg_info.appendAssumeCapacity(DW.OP.bregx);
646 leb128.writeULEB128(dbg_info.writer(), info.fp_register) catch unreachable;
647 }
626648 leb128.writeILEB128(dbg_info.writer(), info.offset) catch unreachable;
627 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
628649 },
629650 .wasm_local => |value| {
630651 const leb_size = link.File.Wasm.getULEB128Size(value);
......@@ -647,8 +668,8 @@ pub const DeclState = struct {
647668
648669 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
649670 const index = dbg_info.items.len;
650 try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4
651 try self.addTypeRelocGlobal(atom_index, ty, @intCast(u32, index)); // DW.AT.type, DW.FORM.ref4
671 try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4
672 try self.addTypeRelocGlobal(atom_index, ty, @intCast(u32, index)); // DW.AT.type, DW.FORM.ref4
652673 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
653674 }
654675
......@@ -670,22 +691,45 @@ pub const DeclState = struct {
670691
671692 switch (loc) {
672693 .register => |reg| {
673 try dbg_info.ensureUnusedCapacity(2);
674 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
675 1, // ULEB128 dwarf expression length
676 reg,
677 });
694 try dbg_info.ensureUnusedCapacity(4);
695 dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));
696 // DW.AT.location, DW.FORM.exprloc
697 var expr_len = std.io.countingWriter(std.io.null_writer);
698 if (reg < 32) {
699 expr_len.writer().writeByte(DW.OP.reg0 + reg) catch unreachable;
700 } else {
701 expr_len.writer().writeByte(DW.OP.regx) catch unreachable;
702 leb128.writeULEB128(expr_len.writer(), reg) catch unreachable;
703 }
704 leb128.writeULEB128(dbg_info.writer(), expr_len.bytes_written) catch unreachable;
705 if (reg < 32) {
706 dbg_info.appendAssumeCapacity(DW.OP.reg0 + reg);
707 } else {
708 dbg_info.appendAssumeCapacity(DW.OP.regx);
709 leb128.writeULEB128(dbg_info.writer(), reg) catch unreachable;
710 }
678711 },
679712
680713 .stack => |info| {
681 try dbg_info.ensureUnusedCapacity(7);
682 const fixup = dbg_info.items.len;
683 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
684 1, // we will backpatch it after we encode the displacement in LEB128
685 info.fp_register,
686 });
714 try dbg_info.ensureUnusedCapacity(9);
715 dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));
716 // DW.AT.location, DW.FORM.exprloc
717 var expr_len = std.io.countingWriter(std.io.null_writer);
718 if (info.fp_register < 32) {
719 expr_len.writer().writeByte(DW.OP.breg0 + info.fp_register) catch unreachable;
720 } else {
721 expr_len.writer().writeByte(DW.OP.bregx) catch unreachable;
722 leb128.writeULEB128(expr_len.writer(), info.fp_register) catch unreachable;
723 }
724 leb128.writeILEB128(expr_len.writer(), info.offset) catch unreachable;
725 leb128.writeULEB128(dbg_info.writer(), expr_len.bytes_written) catch unreachable;
726 if (info.fp_register < 32) {
727 dbg_info.appendAssumeCapacity(DW.OP.breg0 + info.fp_register);
728 } else {
729 dbg_info.appendAssumeCapacity(DW.OP.bregx);
730 leb128.writeULEB128(dbg_info.writer(), info.fp_register) catch unreachable;
731 }
687732 leb128.writeILEB128(dbg_info.writer(), info.offset) catch unreachable;
688 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
689733 },
690734
691735 .wasm_local => |value| {
......@@ -790,7 +834,7 @@ pub const DeclState = struct {
790834
791835 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
792836 const index = dbg_info.items.len;
793 try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4
837 try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4
794838 try self.addTypeRelocGlobal(atom_index, child_ty, @intCast(u32, index));
795839 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
796840 }
......@@ -993,13 +1037,13 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
9931037 // "relocations" and have to be in this fixed place so that functions can be
9941038 // moved in virtual address space.
9951039 assert(dbg_info_low_pc_reloc_index == dbg_info_buffer.items.len);
996 dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT.low_pc, DW.FORM.addr
1040 dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT.low_pc, DW.FORM.addr
9971041 assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len);
998 dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4
1042 dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4
9991043 //
10001044 if (fn_ret_has_bits) {
10011045 try decl_state.addTypeRelocGlobal(di_atom_index, fn_ret_type, @intCast(u32, dbg_info_buffer.items.len));
1002 dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4
1046 dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4
10031047 }
10041048
10051049 dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT.name, DW.FORM.string
......@@ -1619,7 +1663,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
16191663 DW.AT.encoding,
16201664 DW.FORM.data1,
16211665 DW.AT.byte_size,
1622 DW.FORM.data1,
1666 DW.FORM.udata,
16231667 DW.AT.name,
16241668 DW.FORM.string,
16251669 0,
......@@ -1635,7 +1679,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
16351679 DW.TAG.structure_type,
16361680 DW.CHILDREN.yes, // header
16371681 DW.AT.byte_size,
1638 DW.FORM.sdata,
1682 DW.FORM.udata,
16391683 DW.AT.name,
16401684 DW.FORM.string,
16411685 0,
......@@ -1648,14 +1692,14 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
16481692 DW.AT.type,
16491693 DW.FORM.ref4,
16501694 DW.AT.data_member_location,
1651 DW.FORM.sdata,
1695 DW.FORM.udata,
16521696 0,
16531697 0, // table sentinel
16541698 @enumToInt(AbbrevKind.enum_type),
16551699 DW.TAG.enumeration_type,
16561700 DW.CHILDREN.yes, // header
16571701 DW.AT.byte_size,
1658 DW.FORM.sdata,
1702 DW.FORM.udata,
16591703 DW.AT.name,
16601704 DW.FORM.string,
16611705 0,
......@@ -1673,7 +1717,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
16731717 DW.TAG.union_type,
16741718 DW.CHILDREN.yes, // header
16751719 DW.AT.byte_size,
1676 DW.FORM.sdata,
1720 DW.FORM.udata,
16771721 DW.AT.name,
16781722 DW.FORM.string,
16791723 0,
......@@ -2628,7 +2672,7 @@ fn addDbgInfoErrorSet(
26282672
26292673 // DW.AT.enumeration_type
26302674 try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type));
2631 // DW.AT.byte_size, DW.FORM.sdata
2675 // DW.AT.byte_size, DW.FORM.udata
26322676 const abi_size = Type.anyerror.abiSize(target);
26332677 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
26342678 // DW.AT.name, DW.FORM.string
src/type.zig+11-1
......@@ -5433,8 +5433,18 @@ pub const Type = extern union {
54335433 }
54345434 }
54355435
5436 // Works for vectors and vectors of integers.
5437 pub fn maxInt(ty: Type, arena: Allocator, target: Target) !Value {
5438 const scalar = try maxIntScalar(ty.scalarType(), arena, target);
5439 if (ty.zigTypeTag() == .Vector and scalar.tag() != .the_only_possible_value) {
5440 return Value.Tag.repeated.create(arena, scalar);
5441 } else {
5442 return scalar;
5443 }
5444 }
5445
54365446 /// Asserts that self.zigTypeTag() == .Int.
5437 pub fn maxInt(self: Type, arena: Allocator, target: Target) !Value {
5447 pub fn maxIntScalar(self: Type, arena: Allocator, target: Target) !Value {
54385448 assert(self.zigTypeTag() == .Int);
54395449 const info = self.intInfo(target);
54405450
test/behavior/bugs/1277.zig-1
......@@ -14,7 +14,6 @@ fn f() i32 {
1414test "don't emit an LLVM global for a const function when it's in an optional in a struct" {
1515 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1616 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1817 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1918 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2019
test/behavior/bugs/12801-2.zig-1
......@@ -16,7 +16,6 @@ const Auto = struct {
1616test {
1717 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1818 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
19 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2019 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2120 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2221
test/behavior/bugs/13366.zig-1
......@@ -14,7 +14,6 @@ const Block = struct {
1414
1515test {
1616 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1817 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
1918 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2019 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/cast.zig-1
......@@ -153,7 +153,6 @@ test "@intToFloat(f80)" {
153153test "@floatToInt" {
154154 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
155155 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
156 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
157156 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
158157 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
159158 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
test/behavior/field_parent_ptr.zig-4
......@@ -11,7 +11,6 @@ test "@fieldParentPtr non-first field" {
1111}
1212
1313test "@fieldParentPtr first field" {
14 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1514 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1615 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1716 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
......@@ -51,7 +50,6 @@ fn testParentFieldPtrFirst(a: *const bool) !void {
5150}
5251
5352test "@fieldParentPtr untagged union" {
54 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
5553 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
5654 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5755 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -79,7 +77,6 @@ fn testFieldParentPtrUnion(c: *const i32) !void {
7977}
8078
8179test "@fieldParentPtr tagged union" {
82 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8380 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8481 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8582 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -107,7 +104,6 @@ fn testFieldParentPtrTaggedUnion(c: *const i32) !void {
107104}
108105
109106test "@fieldParentPtr extern union" {
110 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
111107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
112108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
113109 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/floatop.zig+1-2
......@@ -184,7 +184,7 @@ test "more @sqrt f16 tests" {
184184test "another, possibly redundant @sqrt test" {
185185 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
186186 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
187 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
187 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
188188 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
189189
190190 try testSqrtLegacy(f64, 12.0);
......@@ -532,7 +532,6 @@ fn testFabs() !void {
532532
533533test "@fabs with vectors" {
534534 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
535 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
536535 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
537536 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
538537 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
test/behavior/fn.zig-1
......@@ -502,7 +502,6 @@ test "method call with optional pointer first param" {
502502}
503503
504504test "using @ptrCast on function pointers" {
505 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
506505 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
507506 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
508507 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/int_comparison_elision.zig-1
......@@ -15,7 +15,6 @@ test "int comparison elision" {
1515
1616 // TODO: support int types > 128 bits wide in other backends
1717 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1918 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2019 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2120
test/behavior/math.zig-3
......@@ -61,7 +61,6 @@ fn assertFalse(b: bool) !void {
6161}
6262
6363test "@clz" {
64 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
6564 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
6665 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6766 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -142,7 +141,6 @@ fn expectVectorsEqual(a: anytype, b: anytype) !void {
142141}
143142
144143test "@ctz" {
145 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
146144 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
147145 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
148146 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1612,7 +1610,6 @@ test "absFloat" {
16121610 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16131611 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16141612 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1615 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
16161613 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
16171614 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
16181615
test/behavior/maximum_minimum.zig-1
......@@ -146,7 +146,6 @@ test "@min/@max more than two arguments" {
146146
147147test "@min/@max more than two vector arguments" {
148148 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
149 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
150149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
151150 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
152151 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/memset.zig-2
......@@ -120,7 +120,6 @@ test "memset with large array element, runtime known" {
120120 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
121121 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
122122 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
123 if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .windows) return error.SkipZigTest;
124123
125124 const A = [128]u64;
126125 var buf: [5]A = undefined;
......@@ -139,7 +138,6 @@ test "memset with large array element, comptime known" {
139138 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
140139 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
141140 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
142 if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .windows) return error.SkipZigTest;
143141
144142 const A = [128]u64;
145143 var buf: [5]A = undefined;
test/behavior/optional.zig-2
......@@ -74,7 +74,6 @@ test "optional with void type" {
7474test "address of unwrap optional" {
7575 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7676 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
7877 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7978 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
8079
......@@ -365,7 +364,6 @@ test "optional pointer to zero bit optional payload" {
365364}
366365
367366test "optional pointer to zero bit error union payload" {
368 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
369367 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
370368 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
371369 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/struct.zig-1
......@@ -1352,7 +1352,6 @@ test "struct field init value is size of the struct" {
13521352}
13531353
13541354test "under-aligned struct field" {
1355 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13561355 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13571356 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13581357 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/translate_c_macros.zig-1
......@@ -65,7 +65,6 @@ test "cast negative integer to pointer" {
6565
6666test "casting to union with a macro" {
6767 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
68 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
6968 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
7069 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7170 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/tuple.zig-1
......@@ -367,7 +367,6 @@ test "branching inside tuple literal" {
367367test "tuple initialized with a runtime known value" {
368368 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
369369 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
370 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
371370 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
372371 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
373372
test/behavior/union.zig-10
......@@ -362,7 +362,6 @@ const MultipleChoice = union(enum(u32)) {
362362 D = 1000,
363363};
364364test "simple union(enum(u32))" {
365 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
366365 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
367366 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
368367 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -641,7 +640,6 @@ test "tagged union with all void fields but a meaningful tag" {
641640}
642641
643642test "union(enum(u32)) with specified and unspecified tag values" {
644 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
645643 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
646644 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
647645 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -821,7 +819,6 @@ test "return union init with void payload" {
821819}
822820
823821test "@unionInit stored to a const" {
824 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
825822 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
826823 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
827824 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
......@@ -994,7 +991,6 @@ test "function call result coerces from tagged union to the tag" {
994991}
995992
996993test "cast from anonymous struct to union" {
997 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
998994 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
999995 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1000996 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
......@@ -1028,7 +1024,6 @@ test "cast from anonymous struct to union" {
10281024}
10291025
10301026test "cast from pointer to anonymous struct to pointer to union" {
1031 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10321027 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10331028 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10341029 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
......@@ -1169,7 +1164,6 @@ test "union enum type gets a separate scope" {
11691164}
11701165
11711166test "global variable struct contains union initialized to non-most-aligned field" {
1172 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11731167 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11741168 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11751169 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1199,7 +1193,6 @@ test "global variable struct contains union initialized to non-most-aligned fiel
11991193test "union with no result loc initiated with a runtime value" {
12001194 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12011195 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1202 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12031196 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12041197 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
12051198
......@@ -1217,7 +1210,6 @@ test "union with no result loc initiated with a runtime value" {
12171210test "union with a large struct field" {
12181211 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12191212 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1220 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12211213 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12221214 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
12231215
......@@ -1288,7 +1280,6 @@ test "extern union most-aligned field is smaller" {
12881280}
12891281
12901282test "return an extern union from C calling convention" {
1291 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12921283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12931284 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12941285 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1397,7 +1388,6 @@ test "union and enum field order doesn't match" {
13971388}
13981389
13991390test "@unionInit uses tag value instead of field index" {
1400 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14011391 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14021392 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14031393 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/vector.zig+2-5
......@@ -26,7 +26,8 @@ test "implicit cast vector to array - bool" {
2626
2727test "vector wrap operators" {
2828 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
29 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
29 if (builtin.zig_backend == .stage2_x86_64 and
30 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO
3031 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
3132 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
3233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -119,7 +120,6 @@ test "vector float operators" {
119120
120121test "vector bit operators" {
121122 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
122 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
123123 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
124124 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
125125 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1129,7 +1129,6 @@ test "loading the second vector from a slice of vectors" {
11291129 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11301130 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11311131 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1132 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11331132
11341133 @setRuntimeSafety(false);
11351134 var small_bases = [2]@Vector(2, u8){
......@@ -1219,7 +1218,6 @@ test "zero multiplicand" {
12191218 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12201219 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12211220 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1222 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12231221
12241222 const zeros = @Vector(2, u32){ 0.0, 0.0 };
12251223 var ones = @Vector(2, u32){ 1.0, 1.0 };
......@@ -1324,7 +1322,6 @@ test "store to vector in slice" {
13241322test "addition of vectors represented as strings" {
13251323 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13261324 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1327 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13281325 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13291326
13301327 const V = @Vector(3, u8);