Skip to content

Commit

Permalink
Merge pull request #15727 from jacobly0/x86_64-behavior
Browse files Browse the repository at this point in the history
x86_64: behavior
  • Loading branch information
andrewrk authored May 19, 2023
2 parents 503302c + 47405b1 commit b873ce1
Show file tree
Hide file tree
Showing 17 changed files with 861 additions and 293 deletions.
951 changes: 706 additions & 245 deletions src/arch/x86_64/CodeGen.zig

Large diffs are not rendered by default.

36 changes: 23 additions & 13 deletions src/arch/x86_64/Encoding.zig
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ pub fn format(
try writer.print("+{s} ", .{tag});
},
.m, .mi, .m1, .mc, .vmi => try writer.print("/{d} ", .{encoding.modRmExt()}),
.mr, .rm, .rmi, .mri, .mrc, .rvm, .rvmi, .mvr => try writer.writeAll("/r "),
.mr, .rm, .rmi, .mri, .mrc, .rm0, .rvm, .rvmr, .rvmi, .mvr => try writer.writeAll("/r "),
}

switch (encoding.data.op_en) {
Expand All @@ -202,7 +202,8 @@ pub fn format(
};
try writer.print("{s} ", .{tag});
},
.np, .fd, .td, .o, .m, .m1, .mc, .mr, .rm, .mrc, .rvm, .mvr => {},
.rvmr => try writer.writeAll("/is4 "),
.np, .fd, .td, .o, .m, .m1, .mc, .mr, .rm, .mrc, .rm0, .rvm, .mvr => {},
}

try writer.print("{s} ", .{@tagName(encoding.mnemonic)});
Expand Down Expand Up @@ -262,6 +263,7 @@ pub const Mnemonic = enum {
fisttp, fld,
// MMX
movd, movq,
packssdw, packsswb, packuswb,
paddb, paddd, paddq, paddsb, paddsw, paddusb, paddusw, paddw,
pand, pandn, por, pxor,
pmulhw, pmullw,
Expand All @@ -270,7 +272,7 @@ pub const Mnemonic = enum {
addps, addss,
andps,
andnps,
cmpss,
cmpps, cmpss,
cvtpi2ps, cvtps2pi, cvtsi2ss, cvtss2si, cvttps2pi, cvttss2si,
divps, divss,
maxps, maxss,
Expand All @@ -290,7 +292,7 @@ pub const Mnemonic = enum {
addpd, addsd,
andpd,
andnpd,
//cmpsd,
cmppd, //cmpsd,
cvtdq2pd, cvtdq2ps, cvtpd2dq, cvtpd2pi, cvtpd2ps, cvtpi2pd,
cvtps2dq, cvtps2pd, cvtsd2si, cvtsd2ss, cvtsi2sd, cvtss2sd,
cvttpd2dq, cvttpd2pi, cvttps2dq, cvttsd2si,
Expand All @@ -315,8 +317,10 @@ pub const Mnemonic = enum {
// SSE3
movddup, movshdup, movsldup,
// SSE4.1
blendpd, blendps, blendvpd, blendvps,
extractps,
insertps,
packusdw,
pextrb, pextrd, pextrq,
pinsrb, pinsrd, pinsrq,
pmaxsb, pmaxsd, pmaxud, pmaxuw, pminsb, pminsd, pminud, pminuw,
Expand All @@ -325,7 +329,9 @@ pub const Mnemonic = enum {
// AVX
vaddpd, vaddps, vaddsd, vaddss,
vandnpd, vandnps, vandpd, vandps,
vblendpd, vblendps, vblendvpd, vblendvps,
vbroadcastf128, vbroadcastsd, vbroadcastss,
vcmppd, vcmpps, vcmpsd, vcmpss,
vcvtdq2pd, vcvtdq2ps, vcvtpd2dq, vcvtpd2ps,
vcvtps2dq, vcvtps2pd, vcvtsd2si, vcvtsd2ss,
vcvtsi2sd, vcvtsi2ss, vcvtss2sd, vcvtss2si,
Expand All @@ -347,6 +353,7 @@ pub const Mnemonic = enum {
vmovupd, vmovups,
vmulpd, vmulps, vmulsd, vmulss,
vorpd, vorps,
vpackssdw, vpacksswb, vpackusdw, vpackuswb,
vpaddb, vpaddd, vpaddq, vpaddsb, vpaddsw, vpaddusb, vpaddusw, vpaddw,
vpand, vpandn,
vpextrb, vpextrd, vpextrq, vpextrw,
Expand Down Expand Up @@ -385,7 +392,7 @@ pub const OpEn = enum {
fd, td,
m1, mc, mi, mr, rm,
rmi, mri, mrc,
vmi, rvm, rvmi, mvr,
rm0, vmi, rvm, rvmr, rvmi, mvr,
// zig fmt: on
};

Expand All @@ -407,7 +414,7 @@ pub const Op = enum {
moffs,
sreg,
st, mm, mm_m64,
xmm, xmm_m32, xmm_m64, xmm_m128,
xmm0, xmm, xmm_m32, xmm_m64, xmm_m128,
ymm, ymm_m256,
// zig fmt: on

Expand Down Expand Up @@ -436,7 +443,9 @@ pub const Op = enum {
.segment => .sreg,
.x87 => .st,
.mmx => .mm,
.sse => switch (reg.bitSize()) {
.sse => if (reg == .xmm0)
.xmm0
else switch (reg.bitSize()) {
128 => .xmm,
256 => .ymm,
else => unreachable,
Expand Down Expand Up @@ -494,7 +503,7 @@ pub const Op = enum {
.eax, .r32, .rm32, .r32_m16 => unreachable,
.rax, .r64, .rm64, .r64_m16 => unreachable,
.st, .mm, .mm_m64 => unreachable,
.xmm, .xmm_m32, .xmm_m64, .xmm_m128 => unreachable,
.xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => unreachable,
.ymm, .ymm_m256 => unreachable,
.m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable,
.unity => 1,
Expand All @@ -516,7 +525,7 @@ pub const Op = enum {
.eax, .r32, .rm32, .r32_m8, .r32_m16 => 32,
.rax, .r64, .rm64, .r64_m16, .mm, .mm_m64 => 64,
.st => 80,
.xmm, .xmm_m32, .xmm_m64, .xmm_m128 => 128,
.xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => 128,
.ymm, .ymm_m256 => 256,
};
}
Expand All @@ -526,7 +535,8 @@ pub const Op = enum {
.none, .o16, .o32, .o64, .moffs, .m, .sreg => unreachable,
.unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable,
.rel8, .rel16, .rel32 => unreachable,
.al, .cl, .r8, .ax, .r16, .eax, .r32, .rax, .r64, .st, .mm, .xmm, .ymm => unreachable,
.al, .cl, .r8, .ax, .r16, .eax, .r32, .rax, .r64 => unreachable,
.st, .mm, .xmm0, .xmm, .ymm => unreachable,
.m8, .rm8, .r32_m8 => 8,
.m16, .rm16, .r32_m16, .r64_m16 => 16,
.m32, .rm32, .xmm_m32 => 32,
Expand Down Expand Up @@ -558,7 +568,7 @@ pub const Op = enum {
.rm8, .rm16, .rm32, .rm64,
.r32_m8, .r32_m16, .r64_m16,
.st, .mm, .mm_m64,
.xmm, .xmm_m32, .xmm_m64, .xmm_m128,
.xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128,
.ymm, .ymm_m256,
=> true,
else => false,
Expand Down Expand Up @@ -612,7 +622,7 @@ pub const Op = enum {
.sreg => .segment,
.st => .x87,
.mm, .mm_m64 => .mmx,
.xmm, .xmm_m32, .xmm_m64, .xmm_m128 => .sse,
.xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => .sse,
.ymm, .ymm_m256 => .sse,
};
}
Expand All @@ -629,7 +639,7 @@ pub const Op = enum {
else => {
if (op.isRegister() and target.isRegister()) {
return switch (target) {
.cl, .al, .ax, .eax, .rax => op == target,
.cl, .al, .ax, .eax, .rax, .xmm0 => op == target,
else => op.class() == target.class() and op.regBitSize() == target.regBitSize(),
};
}
Expand Down
7 changes: 7 additions & 0 deletions src/arch/x86_64/Lower.zig
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
.r => inst.data.r.fixes,
.rr => inst.data.rr.fixes,
.rrr => inst.data.rrr.fixes,
.rrrr => inst.data.rrrr.fixes,
.rrri => inst.data.rrri.fixes,
.rri_s, .rri_u => inst.data.rri.fixes,
.ri_s, .ri_u => inst.data.ri.fixes,
Expand Down Expand Up @@ -430,6 +431,12 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
.{ .reg = inst.data.rrr.r2 },
.{ .reg = inst.data.rrr.r3 },
},
.rrrr => &.{
.{ .reg = inst.data.rrrr.r1 },
.{ .reg = inst.data.rrrr.r2 },
.{ .reg = inst.data.rrrr.r3 },
.{ .reg = inst.data.rrrr.r4 },
},
.rrri => &.{
.{ .reg = inst.data.rrri.r1 },
.{ .reg = inst.data.rrri.r2 },
Expand Down
28 changes: 28 additions & 0 deletions src/arch/x86_64/Mir.zig
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,12 @@ pub const Inst = struct {
/// Bitwise logical xor of packed double-precision floating-point values
xor,

/// Pack with signed saturation
ackssw,
/// Pack with signed saturation
ackssd,
/// Pack with unsigned saturation
ackusw,
/// Add packed signed integers with signed saturation
adds,
/// Add packed unsigned integers with unsigned saturation
Expand Down Expand Up @@ -596,6 +602,18 @@ pub const Inst = struct {
/// Replicate single floating-point values
movsldup,

/// Pack with unsigned saturation
ackusd,
/// Blend packed single-precision floating-point values
/// Blend scalar single-precision floating-point values
/// Blend packed double-precision floating-point values
/// Blend scalar double-precision floating-point values
blend,
/// Variable blend packed single-precision floating-point values
/// Variable blend scalar single-precision floating-point values
/// Variable blend packed double-precision floating-point values
/// Variable blend scalar double-precision floating-point values
blendv,
/// Extract packed floating-point values
extract,
/// Insert scalar single-precision floating-point value
Expand Down Expand Up @@ -651,6 +669,9 @@ pub const Inst = struct {
/// Register, register, register operands.
/// Uses `rrr` payload.
rrr,
/// Register, register, register, register operands.
/// Uses `rrrr` payload.
rrrr,
/// Register, register, register, immediate (byte) operands.
/// Uses `rrri` payload.
rrri,
Expand Down Expand Up @@ -870,6 +891,13 @@ pub const Inst = struct {
r2: Register,
r3: Register,
},
rrrr: struct {
fixes: Fixes = ._,
r1: Register,
r2: Register,
r3: Register,
r4: Register,
},
rrri: struct {
fixes: Fixes = ._,
r1: Register,
Expand Down
31 changes: 16 additions & 15 deletions src/arch/x86_64/encoder.zig
Original file line number Diff line number Diff line change
Expand Up @@ -226,16 +226,16 @@ pub const Instruction = struct {
else => {
const mem_op = switch (data.op_en) {
.m, .mi, .m1, .mc, .mr, .mri, .mrc, .mvr => inst.ops[0],
.rm, .rmi, .vmi => inst.ops[1],
.rvm, .rvmi => inst.ops[2],
.rm, .rmi, .rm0, .vmi => inst.ops[1],
.rvm, .rvmr, .rvmi => inst.ops[2],
else => unreachable,
};
switch (mem_op) {
.reg => |reg| {
const rm = switch (data.op_en) {
.m, .mi, .m1, .mc, .vmi => enc.modRmExt(),
.mr, .mri, .mrc => inst.ops[1].reg.lowEnc(),
.rm, .rmi, .rvm, .rvmi => inst.ops[0].reg.lowEnc(),
.rm, .rmi, .rm0, .rvm, .rvmr, .rvmi => inst.ops[0].reg.lowEnc(),
.mvr => inst.ops[2].reg.lowEnc(),
else => unreachable,
};
Expand All @@ -245,7 +245,7 @@ pub const Instruction = struct {
const op = switch (data.op_en) {
.m, .mi, .m1, .mc, .vmi => .none,
.mr, .mri, .mrc => inst.ops[1],
.rm, .rmi, .rvm, .rvmi => inst.ops[0],
.rm, .rmi, .rm0, .rvm, .rvmr, .rvmi => inst.ops[0],
.mvr => inst.ops[2],
else => unreachable,
};
Expand All @@ -257,6 +257,7 @@ pub const Instruction = struct {
switch (data.op_en) {
.mi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder),
.rmi, .mri, .vmi => try encodeImm(inst.ops[2].imm, data.ops[2], encoder),
.rvmr => try encoder.imm8(@as(u8, inst.ops[3].reg.enc()) << 4),
.rvmi => try encodeImm(inst.ops[3].imm, data.ops[3], encoder),
else => {},
}
Expand Down Expand Up @@ -298,7 +299,7 @@ pub const Instruction = struct {
.i, .zi, .o, .oi, .d, .np => null,
.fd => inst.ops[1].mem.base().reg,
.td => inst.ops[0].mem.base().reg,
.rm, .rmi => if (inst.ops[1].isSegmentRegister())
.rm, .rmi, .rm0 => if (inst.ops[1].isSegmentRegister())
switch (inst.ops[1]) {
.reg => |reg| reg,
.mem => |mem| mem.base().reg,
Expand All @@ -314,7 +315,7 @@ pub const Instruction = struct {
}
else
null,
.vmi, .rvm, .rvmi, .mvr => unreachable,
.vmi, .rvm, .rvmr, .rvmi, .mvr => unreachable,
};
if (segment_override) |seg| {
legacy.setSegmentOverride(seg);
Expand All @@ -333,23 +334,23 @@ pub const Instruction = struct {
switch (op_en) {
.np, .i, .zi, .fd, .td, .d => {},
.o, .oi => rex.b = inst.ops[0].reg.isExtended(),
.m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc => {
.m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc, .rm0 => {
const r_op = switch (op_en) {
.rm, .rmi => inst.ops[0],
.rm, .rmi, .rm0 => inst.ops[0],
.mr, .mri, .mrc => inst.ops[1],
else => .none,
};
rex.r = r_op.isBaseExtended();

const b_x_op = switch (op_en) {
.rm, .rmi => inst.ops[1],
.rm, .rmi, .rm0 => inst.ops[1],
.m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.ops[0],
else => unreachable,
};
rex.b = b_x_op.isBaseExtended();
rex.x = b_x_op.isIndexExtended();
},
.vmi, .rvm, .rvmi, .mvr => unreachable,
.vmi, .rvm, .rvmr, .rvmi, .mvr => unreachable,
}

try encoder.rex(rex);
Expand All @@ -367,9 +368,9 @@ pub const Instruction = struct {
switch (op_en) {
.np, .i, .zi, .fd, .td, .d => {},
.o, .oi => vex.b = inst.ops[0].reg.isExtended(),
.m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc, .vmi, .rvm, .rvmi, .mvr => {
.m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc, .rm0, .vmi, .rvm, .rvmr, .rvmi, .mvr => {
const r_op = switch (op_en) {
.rm, .rmi, .rvm, .rvmi => inst.ops[0],
.rm, .rmi, .rm0, .rvm, .rvmr, .rvmi => inst.ops[0],
.mr, .mri, .mrc => inst.ops[1],
.mvr => inst.ops[2],
.m, .mi, .m1, .mc, .vmi => .none,
Expand All @@ -378,9 +379,9 @@ pub const Instruction = struct {
vex.r = r_op.isBaseExtended();

const b_x_op = switch (op_en) {
.rm, .rmi, .vmi => inst.ops[1],
.rm, .rmi, .rm0, .vmi => inst.ops[1],
.m, .mi, .m1, .mc, .mr, .mri, .mrc, .mvr => inst.ops[0],
.rvm, .rvmi => inst.ops[2],
.rvm, .rvmr, .rvmi => inst.ops[2],
else => unreachable,
};
vex.b = b_x_op.isBaseExtended();
Expand Down Expand Up @@ -408,7 +409,7 @@ pub const Instruction = struct {
switch (op_en) {
else => {},
.vmi => vex.v = inst.ops[0].reg,
.rvm, .rvmi => vex.v = inst.ops[1].reg,
.rvm, .rvmr, .rvmi => vex.v = inst.ops[1].reg,
}

try encoder.vex(vex);
Expand Down
Loading

0 comments on commit b873ce1

Please sign in to comment.