| author | |
| committer | |
| log | ff7412752690d1690cfaedaa605128a992a6b280 |
| tree | 157e66cd89cf8f5b97c853c9e8f18d3235f372a4 |
| parent | 82eedf56d703b3ce659519fe52f58a06279cfde0 |
4 files changed, 80 insertions(+), 21 deletions(-)
src/arch/x86_64/CodeGen.zig+27-6| ... | ... | @@ -2484,7 +2484,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2484 | 2484 | .reduce => try cg.airReduce(inst), |
| 2485 | 2485 | .reduce_optimized => try cg.airReduce(inst), |
| 2486 | 2486 | .aggregate_init => try cg.airAggregateInit(inst), |
| 2487 | .prefetch => try cg.airPrefetch(inst), | |
| 2488 | 2487 | // zig fmt: on |
| 2489 | 2488 | |
| 2490 | 2489 | .arg => if (cg.debug_output != .none) { |
| ... | ... | @@ -76418,6 +76417,33 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 76418 | 76417 | }, cg); |
| 76419 | 76418 | try res.finish(inst, &.{extra.init}, &ops, cg); |
| 76420 | 76419 | }, |
| 76420 | .prefetch => { | |
| 76421 | const prefetch = air_datas[@intFromEnum(inst)].prefetch; | |
| 76422 | var ops = try cg.tempsFromOperands(inst, .{prefetch.ptr}); | |
| 76423 | switch (prefetch.cache) { | |
| 76424 | .instruction => {}, // prefetchi requires rip-relative addressing, which is currently non-trivial to emit from an arbitrary ptr value | |
| 76425 | .data => if (prefetch.rw == .write and prefetch.locality <= 2 and cg.hasFeature(.prefetchwt1)) { | |
| 76426 | try ops[0].toSlicePtr(cg); | |
| 76427 | while (try ops[0].toLea(cg)) {} | |
| 76428 | try cg.asmMemory(.{ ._wt1, .prefetch }, try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = .byte })); | |
| 76429 | } else if (prefetch.rw == .write and cg.hasFeature(.prfchw)) { | |
| 76430 | try ops[0].toSlicePtr(cg); | |
| 76431 | while (try ops[0].toLea(cg)) {} | |
| 76432 | try cg.asmMemory(.{ ._w, .prefetch }, try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = .byte })); | |
| 76433 | } else if (cg.hasFeature(.sse) or cg.hasFeature(.prfchw) or cg.hasFeature(.prefetchi) or cg.hasFeature(.prefetchwt1)) { | |
| 76434 | try ops[0].toSlicePtr(cg); | |
| 76435 | while (try ops[0].toLea(cg)) {} | |
| 76436 | switch (prefetch.locality) { | |
| 76437 | 0 => try cg.asmMemory(.{ ._nta, .prefetch }, try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = .byte })), | |
| 76438 | 1 => try cg.asmMemory(.{ ._t2, .prefetch }, try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = .byte })), | |
| 76439 | 2 => try cg.asmMemory(.{ ._t1, .prefetch }, try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = .byte })), | |
| 76440 | 3 => try cg.asmMemory(.{ ._t0, .prefetch }, try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = .byte })), | |
| 76441 | } | |
| 76442 | }, | |
| 76443 | } | |
| 76444 | const res = try cg.tempInit(.void, .none); | |
| 76445 | try res.finish(inst, &.{prefetch.ptr}, &ops, cg); | |
| 76446 | }, | |
| 76421 | 76447 | .mul_add => |air_tag| if (use_old) try cg.airMulAdd(inst) else { |
| 76422 | 76448 | const pl_op = air_datas[@intFromEnum(inst)].pl_op; |
| 76423 | 76449 | const bin_op = cg.air.extraData(Air.Bin, pl_op.payload).data; |
| ... | ... | @@ -94743,11 +94769,6 @@ fn airUnionInit(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 94743 | 94769 | return self.finishAir(inst, result, .{ extra.init, .none, .none }); |
| 94744 | 94770 | } |
| 94745 | 94771 | |
| 94746 | fn airPrefetch(self: *CodeGen, inst: Air.Inst.Index) !void { | |
| 94747 | const prefetch = self.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; | |
| 94748 | return self.finishAir(inst, .unreach, .{ prefetch.ptr, .none, .none }); | |
| 94749 | } | |
| 94750 | ||
| 94751 | 94772 | fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 94752 | 94773 | const pt = self.pt; |
| 94753 | 94774 | const zcu = pt.zcu; |
src/arch/x86_64/Encoding.zig+27-15| ... | ... | @@ -78,7 +78,7 @@ pub fn findByMnemonic( |
| 78 | 78 | ), |
| 79 | 79 | .x86_64 => false, |
| 80 | 80 | }, |
| 81 | inline .@"invpcid 64bit", .@"rdpid 64bit" => |tag| switch (target.cpu.arch) { | |
| 81 | inline .@"invpcid 64bit", .@"rdpid 64bit", .@"prefetchi 64bit" => |tag| switch (target.cpu.arch) { | |
| 82 | 82 | else => unreachable, |
| 83 | 83 | .x86 => false, |
| 84 | 84 | .x86_64 => std.Target.x86.featureSetHas( |
| ... | ... | @@ -86,6 +86,7 @@ pub fn findByMnemonic( |
| 86 | 86 | @field(std.Target.x86.Feature, @tagName(tag)[0 .. @tagName(tag).len - " 64bit".len]), |
| 87 | 87 | ), |
| 88 | 88 | }, |
| 89 | .prefetch => std.Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .prfchw, .prefetchi, .prefetchwt1 }), | |
| 89 | 90 | inline else => |tag| has_features: { |
| 90 | 91 | comptime var feature_it = std.mem.splitScalar(u8, @tagName(tag), ' '); |
| 91 | 92 | comptime var features: []const std.Target.x86.Feature = &.{}; |
| ... | ... | @@ -375,6 +376,7 @@ pub const Mnemonic = enum { |
| 375 | 376 | orps, |
| 376 | 377 | pextrw, pinsrw, |
| 377 | 378 | pmaxsw, pmaxub, pminsw, pminub, pmovmskb, |
| 379 | prefetchit0, prefetchit1, prefetchnta, prefetcht0, prefetcht1, prefetcht2, prefetchw, prefetchwt1, | |
| 378 | 380 | shufps, |
| 379 | 381 | sqrtps, sqrtss, |
| 380 | 382 | stmxcsr, |
| ... | ... | @@ -562,8 +564,7 @@ pub const Op = enum { |
| 562 | 564 | r32_m8, r32_m16, r64_m16, |
| 563 | 565 | m8, m16, m32, m64, m80, m128, m256, |
| 564 | 566 | rel8, rel16, rel32, |
| 565 | m, | |
| 566 | moffs, | |
| 567 | m, moffs, mrip8, | |
| 567 | 568 | sreg, |
| 568 | 569 | st0, st, mm, mm_m64, |
| 569 | 570 | xmm0, xmm, xmm_m8, xmm_m16, xmm_m32, xmm_m64, xmm_m128, |
| ... | ... | @@ -617,7 +618,7 @@ pub const Op = enum { |
| 617 | 618 | |
| 618 | 619 | .mem => |mem| switch (mem) { |
| 619 | 620 | .moffs => .moffs, |
| 620 | .sib, .rip => switch (mem.bitSize(target)) { | |
| 621 | .sib => switch (mem.bitSize(target)) { | |
| 621 | 622 | 0 => .m, |
| 622 | 623 | 8 => .m8, |
| 623 | 624 | 16 => .m16, |
| ... | ... | @@ -628,6 +629,16 @@ pub const Op = enum { |
| 628 | 629 | 256 => .m256, |
| 629 | 630 | else => unreachable, |
| 630 | 631 | }, |
| 632 | .rip => switch (mem.bitSize(target)) { | |
| 633 | 0, 8 => .mrip8, | |
| 634 | 16 => .m16, | |
| 635 | 32 => .m32, | |
| 636 | 64 => .m64, | |
| 637 | 80 => .m80, | |
| 638 | 128 => .m128, | |
| 639 | 256 => .m256, | |
| 640 | else => unreachable, | |
| 641 | }, | |
| 631 | 642 | }, |
| 632 | 643 | |
| 633 | 644 | .imm => |imm| switch (imm) { |
| ... | ... | @@ -680,7 +691,7 @@ pub const Op = enum { |
| 680 | 691 | |
| 681 | 692 | pub fn immBitSize(op: Op) u64 { |
| 682 | 693 | return switch (op) { |
| 683 | .none, .moffs, .m, .sreg => unreachable, | |
| 694 | .none, .m, .moffs, .mrip8, .sreg => unreachable, | |
| 684 | 695 | .al, .cl, .dx, .rip, .eip, .ip, .r8, .rm8, .r32_m8 => unreachable, |
| 685 | 696 | .ax, .r16, .rm16 => unreachable, |
| 686 | 697 | .eax, .r32, .rm32, .r32_m16 => unreachable, |
| ... | ... | @@ -700,7 +711,7 @@ pub const Op = enum { |
| 700 | 711 | |
| 701 | 712 | pub fn regBitSize(op: Op) u64 { |
| 702 | 713 | return switch (op) { |
| 703 | .none, .moffs, .m, .sreg => unreachable, | |
| 714 | .none, .m, .moffs, .mrip8, .sreg => unreachable, | |
| 704 | 715 | .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable, |
| 705 | 716 | .rel8, .rel16, .rel32 => unreachable, |
| 706 | 717 | .m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable, |
| ... | ... | @@ -716,13 +727,13 @@ pub const Op = enum { |
| 716 | 727 | |
| 717 | 728 | pub fn memBitSize(op: Op) u64 { |
| 718 | 729 | return switch (op) { |
| 719 | .none, .moffs, .m, .sreg => unreachable, | |
| 730 | .none, .m, .moffs, .sreg => unreachable, | |
| 720 | 731 | .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable, |
| 721 | 732 | .rel8, .rel16, .rel32 => unreachable, |
| 722 | 733 | .al, .cl, .r8, .ax, .dx, .ip, .r16, .eax, .eip, .r32, .rax, .rip, .r64 => unreachable, |
| 723 | 734 | .st0, .st, .mm, .xmm0, .xmm, .ymm => unreachable, |
| 724 | 735 | .cr, .dr => unreachable, |
| 725 | .m8, .rm8, .r32_m8, .xmm_m8 => 8, | |
| 736 | .mrip8, .m8, .rm8, .r32_m8, .xmm_m8 => 8, | |
| 726 | 737 | .m16, .rm16, .r32_m16, .r64_m16, .xmm_m16 => 16, |
| 727 | 738 | .m32, .rm32, .xmm_m32 => 32, |
| 728 | 739 | .m64, .rm64, .mm_m64, .xmm_m64 => 64, |
| ... | ... | @@ -783,7 +794,7 @@ pub const Op = enum { |
| 783 | 794 | .rm8, .rm16, .rm32, .rm64, |
| 784 | 795 | .r32_m8, .r32_m16, .r64_m16, |
| 785 | 796 | .m8, .m16, .m32, .m64, .m80, .m128, .m256, |
| 786 | .m, | |
| 797 | .m, .moffs, .mrip8, | |
| 787 | 798 | .mm_m64, |
| 788 | 799 | .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128, |
| 789 | 800 | .ymm_m256, |
| ... | ... | @@ -821,11 +832,7 @@ pub const Op = enum { |
| 821 | 832 | /// Given an operand `op` checks if `target` is a subset for the purposes of the encoding. |
| 822 | 833 | pub fn isSubset(op: Op, target: Op) bool { |
| 823 | 834 | switch (op) { |
| 824 | .moffs, .sreg => return op == target, | |
| 825 | .none => switch (target) { | |
| 826 | .none => return true, | |
| 827 | else => return false, | |
| 828 | }, | |
| 835 | .none, .m, .moffs, .sreg => return op == target, | |
| 829 | 836 | else => { |
| 830 | 837 | if (op.isRegister() and target.isRegister()) { |
| 831 | 838 | return switch (target.toReg()) { |
| ... | ... | @@ -836,6 +843,7 @@ pub const Op = enum { |
| 836 | 843 | if (op.isMemory() and target.isMemory()) { |
| 837 | 844 | switch (target) { |
| 838 | 845 | .m => return true, |
| 846 | .moffs, .mrip8 => return op == target, | |
| 839 | 847 | else => return op.memBitSize() == target.memBitSize(), |
| 840 | 848 | } |
| 841 | 849 | } |
| ... | ... | @@ -962,6 +970,10 @@ pub const Feature = enum { |
| 962 | 970 | @"pclmul avx", |
| 963 | 971 | pku, |
| 964 | 972 | popcnt, |
| 973 | prefetch, | |
| 974 | @"prefetchi 64bit", | |
| 975 | prefetchwt1, | |
| 976 | prfchw, | |
| 965 | 977 | rdrnd, |
| 966 | 978 | rdseed, |
| 967 | 979 | @"rdpid 32bit", |
| ... | ... | @@ -1002,7 +1014,7 @@ fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Op |
| 1002 | 1014 | } |
| 1003 | 1015 | |
| 1004 | 1016 | const mnemonic_to_encodings_map = init: { |
| 1005 | @setEvalBranchQuota(5_700); | |
| 1017 | @setEvalBranchQuota(5_800); | |
| 1006 | 1018 | const mnemonic_count = @typeInfo(Mnemonic).@"enum".fields.len; |
| 1007 | 1019 | var mnemonic_map: [mnemonic_count][]Data = @splat(&.{}); |
| 1008 | 1020 | const encodings = @import("encodings.zig"); |
src/arch/x86_64/Mir.zig+14| ... | ... | @@ -34,8 +34,18 @@ pub const Inst = struct { |
| 34 | 34 | /// ___ 4 |
| 35 | 35 | _4, |
| 36 | 36 | |
| 37 | /// ___ With NTA Hint | |
| 38 | _nta, | |
| 37 | 39 | /// System Call ___ |
| 38 | 40 | sys_, |
| 41 | /// ___ With T0 Hint | |
| 42 | _t0, | |
| 43 | /// ___ With T1 Hint | |
| 44 | _t1, | |
| 45 | /// ___ With T2 Hint | |
| 46 | _t2, | |
| 47 | /// ___ With Intent to Write and T1 Hint | |
| 48 | _wt1, | |
| 39 | 49 | |
| 40 | 50 | /// ___ crement Shadow Stack Pointer Doubleword |
| 41 | 51 | _csspd, |
| ... | ... | @@ -198,6 +208,7 @@ pub const Inst = struct { |
| 198 | 208 | //_b, |
| 199 | 209 | /// ___ Word |
| 200 | 210 | /// ___ For Writing |
| 211 | /// ___ With Intent to Write | |
| 201 | 212 | _w, |
| 202 | 213 | /// ___ Doubleword |
| 203 | 214 | //_d, |
| ... | ... | @@ -975,6 +986,9 @@ pub const Inst = struct { |
| 975 | 986 | /// Move unaligned packed single-precision floating-point values |
| 976 | 987 | /// Move unaligned packed double-precision floating-point values |
| 977 | 988 | movu, |
| 989 | /// Prefetch data into caches | |
| 990 | /// Prefetch data into caches with intent to write | |
| 991 | prefetch, | |
| 978 | 992 | /// Packed interleave shuffle of quadruplets of single-precision floating-point values |
| 979 | 993 | /// Packed interleave shuffle of pairs of double-precision floating-point values |
| 980 | 994 | /// Shuffle packed doublewords |
src/arch/x86_64/encodings.zig+12| ... | ... | @@ -1370,6 +1370,18 @@ pub const table = [_]Entry{ |
| 1370 | 1370 | .{ .pmovmskb, .rm, &.{ .r32, .xmm }, &.{ 0x66, 0x0f, 0xd7 }, 0, .none, .sse }, |
| 1371 | 1371 | .{ .pmovmskb, .rm, &.{ .r64, .xmm }, &.{ 0x66, 0x0f, 0xd7 }, 0, .none, .sse }, |
| 1372 | 1372 | |
| 1373 | .{ .prefetchit0, .m, &.{ .mrip8 }, &.{ 0x0f, 0x18 }, 7, .none, .@"prefetchi 64bit" }, | |
| 1374 | .{ .prefetchit1, .m, &.{ .mrip8 }, &.{ 0x0f, 0x18 }, 6, .none, .@"prefetchi 64bit" }, | |
| 1375 | ||
| 1376 | .{ .prefetchnta, .m, &.{ .m8 }, &.{ 0x0f, 0x18 }, 0, .none, .prefetch }, | |
| 1377 | .{ .prefetcht0, .m, &.{ .m8 }, &.{ 0x0f, 0x18 }, 1, .none, .prefetch }, | |
| 1378 | .{ .prefetcht1, .m, &.{ .m8 }, &.{ 0x0f, 0x18 }, 2, .none, .prefetch }, | |
| 1379 | .{ .prefetcht2, .m, &.{ .m8 }, &.{ 0x0f, 0x18 }, 3, .none, .prefetch }, | |
| 1380 | ||
| 1381 | .{ .prefetchw, .m, &.{ .m8 }, &.{ 0x0f, 0x0d }, 1, .none, .prfchw }, | |
| 1382 | ||
| 1383 | .{ .prefetchwt1, .m, &.{ .m8 }, &.{ 0x0f, 0x0d }, 2, .none, .prefetchwt1 }, | |
| 1384 | ||
| 1373 | 1385 | .{ .shufps, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x0f, 0xc6 }, 0, .none, .sse }, |
| 1374 | 1386 | |
| 1375 | 1387 | .{ .sqrtps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x51 }, 0, .none, .sse }, |