x86_64: reimplement @floatToInt

This commit is contained in:
Jacob Young 2023-05-13 18:06:16 -04:00
parent e08eab6648
commit b6d6102850
7 changed files with 422 additions and 255 deletions

View File

@ -2501,12 +2501,12 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
}
} else if (src_bits == 64 and dst_bits == 32) {
if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
.{ .v_, .cvtsd2ss },
.{ .v_ss, .cvtsd2 },
dst_reg,
dst_reg,
src_mcv.mem(.qword),
) else try self.asmRegisterRegisterRegister(
.{ .v_, .cvtsd2ss },
.{ .v_ss, .cvtsd2 },
dst_reg,
dst_reg,
(if (src_mcv.isRegister())
@ -2514,11 +2514,11 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
else
try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
.{ ._, .cvtsd2ss },
.{ ._ss, .cvtsd2 },
dst_reg,
src_mcv.mem(.qword),
) else try self.asmRegisterRegister(
.{ ._, .cvtsd2ss },
.{ ._ss, .cvtsd2 },
dst_reg,
(if (src_mcv.isRegister())
src_mcv.getReg().?
@ -2552,22 +2552,22 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
src_mcv.getReg().?
else
try self.copyToTmpRegister(src_ty, src_mcv);
try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, mat_src_reg.to128());
try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, mat_src_reg.to128());
switch (dst_bits) {
32 => {},
64 => try self.asmRegisterRegisterRegister(.{ .v_, .cvtss2sd }, dst_reg, dst_reg, dst_reg),
64 => try self.asmRegisterRegisterRegister(.{ .v_sd, .cvtss2 }, dst_reg, dst_reg, dst_reg),
else => return self.fail("TODO implement airFpext from {} to {}", .{
src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
}),
}
} else if (src_bits == 32 and dst_bits == 64) {
if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
.{ .v_, .cvtss2sd },
.{ .v_sd, .cvtss2 },
dst_reg,
dst_reg,
src_mcv.mem(.dword),
) else try self.asmRegisterRegisterRegister(
.{ .v_, .cvtss2sd },
.{ .v_sd, .cvtss2 },
dst_reg,
dst_reg,
(if (src_mcv.isRegister())
@ -2575,11 +2575,11 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
else
try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
.{ ._, .cvtss2sd },
.{ ._sd, .cvtss2 },
dst_reg,
src_mcv.mem(.dword),
) else try self.asmRegisterRegister(
.{ ._, .cvtss2sd },
.{ ._sd, .cvtss2 },
dst_reg,
(if (src_mcv.isRegister())
src_mcv.getReg().?
@ -4789,7 +4789,6 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
})) |tag| tag else return self.fail("TODO implement genRound for {}", .{
ty.fmt(self.bin_file.options.module.?),
});
const abi_size = @intCast(u32, ty.abiSize(self.target.*));
const dst_alias = registerAlias(dst_reg, abi_size);
switch (mir_tag[0]) {
@ -4848,7 +4847,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
src_mcv.getReg().?
else
try self.copyToTmpRegister(ty, src_mcv);
try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, mat_src_reg.to128());
try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, mat_src_reg.to128());
try self.asmRegisterRegisterRegister(.{ .v_ss, .sqrt }, dst_reg, dst_reg, dst_reg);
try self.asmRegisterRegisterImmediate(
.{ .v_, .cvtps2ph },
@ -4868,7 +4867,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
16 => if (self.hasFeature(.f16c)) switch (ty.vectorLen()) {
1 => {
try self.asmRegisterRegister(
.{ .v_, .cvtph2ps },
.{ .v_ps, .cvtph2 },
dst_reg,
(if (src_mcv.isRegister())
src_mcv.getReg().?
@ -4892,13 +4891,13 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
2...8 => {
const wide_reg = registerAlias(dst_reg, abi_size * 2);
if (src_mcv.isMemory()) try self.asmRegisterMemory(
.{ .v_, .cvtph2ps },
.{ .v_ps, .cvtph2 },
wide_reg,
src_mcv.mem(Memory.PtrSize.fromSize(
@intCast(u32, @divExact(wide_reg.bitSize(), 16)),
)),
) else try self.asmRegisterRegister(
.{ .v_, .cvtph2ps },
.{ .v_ps, .cvtph2 },
wide_reg,
(if (src_mcv.isRegister())
src_mcv.getReg().?
@ -6347,7 +6346,7 @@ fn genBinOp(
else
try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
);
try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, dst_reg);
try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp_reg, dst_reg);
try self.asmRegisterRegisterRegister(
switch (air_tag) {
@ -6424,7 +6423,7 @@ fn genBinOp(
else
try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
);
try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, dst_reg);
try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp_reg, dst_reg);
try self.asmRegisterRegisterRegister(
switch (air_tag) {
@ -6467,7 +6466,7 @@ fn genBinOp(
else
try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
);
try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, dst_reg);
try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
try self.asmRegisterRegisterRegister(
.{ .v_ps, .movhl },
tmp_reg,
@ -6501,13 +6500,13 @@ fn genBinOp(
const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
defer self.register_manager.unlockReg(tmp_lock);
try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, dst_reg);
try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
if (src_mcv.isMemory()) try self.asmRegisterMemory(
.{ .v_, .cvtph2ps },
.{ .v_ps, .cvtph2 },
tmp_reg,
src_mcv.mem(.qword),
) else try self.asmRegisterRegister(
.{ .v_, .cvtph2ps },
.{ .v_ps, .cvtph2 },
tmp_reg,
(if (src_mcv.isRegister())
src_mcv.getReg().?
@ -6541,13 +6540,13 @@ fn genBinOp(
const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
defer self.register_manager.unlockReg(tmp_lock);
try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg.to256(), dst_reg);
try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg.to256(), dst_reg);
if (src_mcv.isMemory()) try self.asmRegisterMemory(
.{ .v_, .cvtph2ps },
.{ .v_ps, .cvtph2 },
tmp_reg,
src_mcv.mem(.xword),
) else try self.asmRegisterRegister(
.{ .v_, .cvtph2ps },
.{ .v_ps, .cvtph2 },
tmp_reg,
(if (src_mcv.isRegister())
src_mcv.getReg().?
@ -7199,13 +7198,13 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void {
switch (self.debug_output) {
.dwarf => |dw| {
const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {
.register => |reg| .{ .register = reg.dwarfLocOp() },
.register => |reg| .{ .register = reg.dwarfNum() },
// TODO use a frame index
.load_frame => return,
//.stack_offset => |off| .{
// .stack = .{
// // TODO handle -fomit-frame-pointer
// .fp_register = Register.rbp.dwarfLocOpDeref(),
// .fp_register = Register.rbp.dwarfNum(),
// .offset = -off,
// },
//},
@ -7237,11 +7236,11 @@ fn genVarDbgInfo(
switch (self.debug_output) {
.dwarf => |dw| {
const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {
.register => |reg| .{ .register = reg.dwarfLocOp() },
.register => |reg| .{ .register = reg.dwarfNum() },
// TODO use a frame index
.load_frame, .lea_frame => return,
//=> |off| .{ .stack = .{
// .fp_register = Register.rbp.dwarfLocOpDeref(),
// .fp_register = Register.rbp.dwarfNum(),
// .offset = -off,
//} },
.memory => |address| .{ .memory = address },
@ -7595,7 +7594,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
else
try self.copyToTmpRegister(ty, src_mcv)).to128(),
);
try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, tmp1_reg, tmp1_reg);
try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, tmp1_reg, tmp1_reg);
try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp2_reg, tmp1_reg);
try self.genBinOpMir(.{ ._ss, .ucomi }, ty, tmp1_mcv, tmp2_mcv);
} else return self.fail("TODO implement airCmp for {}", .{
@ -8862,14 +8861,14 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
}
},
.register => |src_reg| if (dst_reg.id() != src_reg.id()) try self.asmRegisterRegister(
if ((dst_reg.class() == .floating_point) == (src_reg.class() == .floating_point))
if ((dst_reg.class() == .sse) == (src_reg.class() == .sse))
switch (ty.zigTypeTag()) {
else => .{ ._, .mov },
.Float, .Vector => .{ ._ps, .mova },
}
else switch (abi_size) {
2 => return try self.asmRegisterRegisterImmediate(
if (dst_reg.class() == .floating_point) .{ .p_w, .insr } else .{ .p_w, .extr },
if (dst_reg.class() == .sse) .{ .p_w, .insr } else .{ .p_w, .extr },
registerAlias(dst_reg, 4),
registerAlias(src_reg, 4),
Immediate.u(0),
@ -9222,7 +9221,7 @@ fn genInlineMemcpyRegisterRegister(
try self.asmMemoryRegister(
switch (src_reg.class()) {
.general_purpose, .segment => .{ ._, .mov },
.floating_point => .{ ._ss, .mov },
.sse => .{ ._ss, .mov },
},
Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = dst_reg, .disp = -offset }),
registerAlias(src_reg, abi_size),
@ -9388,10 +9387,10 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
});
const src_mcv = try self.resolveInst(ty_op.operand);
const src_reg = switch (src_mcv) {
.register => |reg| reg,
else => try self.copyToTmpRegister(src_ty, src_mcv),
};
const src_reg = if (src_mcv.isRegister())
src_mcv.getReg().?
else
try self.copyToTmpRegister(src_ty, src_mcv);
const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
defer self.register_manager.unlockReg(src_lock);
@ -9402,23 +9401,23 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
defer self.register_manager.unlockReg(dst_lock);
try self.asmRegisterRegister(switch (dst_ty.floatBits(self.target.*)) {
32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse))
.{ ._, .cvtsi2ss }
else
return self.fail("TODO implement airIntToFloat from {} to {} without sse", .{
src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
}),
64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2))
.{ ._, .cvtsi2sd }
else
return self.fail("TODO implement airIntToFloat from {} to {} without sse2", .{
src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
}),
else => return self.fail("TODO implement airIntToFloat from {} to {}", .{
src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
}),
}, dst_reg.to128(), registerAlias(src_reg, src_size));
const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_ty.zigTypeTag()) {
.Float => switch (dst_ty.floatBits(self.target.*)) {
32 => if (self.hasFeature(.avx)) .{ .v_ss, .cvtsi2 } else .{ ._ss, .cvtsi2 },
64 => if (self.hasFeature(.avx)) .{ .v_sd, .cvtsi2 } else .{ ._sd, .cvtsi2 },
16, 80, 128 => null,
else => unreachable,
},
else => null,
})) |tag| tag else return self.fail("TODO implement airIntToFloat from {} to {}", .{
src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
});
const dst_alias = dst_reg.to128();
const src_alias = registerAlias(src_reg, src_size);
switch (mir_tag[0]) {
.v_ss, .v_sd => try self.asmRegisterRegisterRegister(mir_tag, dst_alias, dst_alias, src_alias),
else => try self.asmRegisterRegister(mir_tag, dst_alias, src_alias),
}
return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
}
@ -9428,46 +9427,50 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
const src_ty = self.air.typeOf(ty_op.operand);
const dst_ty = self.air.typeOfIndex(inst);
const operand = try self.resolveInst(ty_op.operand);
const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));
const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
const dst_bits = @intCast(u32, dst_ty.bitSize(self.target.*));
const dst_signedness =
if (dst_ty.isAbiInt()) dst_ty.intInfo(self.target.*).signedness else .unsigned;
switch (src_abi_size) {
4, 8 => {},
else => |size| return self.fail("TODO load ST(0) with abiSize={}", .{size}),
}
if (dst_abi_size > 8) {
return self.fail("TODO convert float with abiSize={}", .{dst_abi_size});
}
const dst_size = std.math.divCeil(u32, @max(switch (dst_signedness) {
.signed => dst_bits,
.unsigned => dst_bits + 1,
}, 32), 8) catch unreachable;
if (dst_size > 8) return self.fail("TODO implement airFloatToInt from {} to {}", .{
src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
});
// move float src to ST(0)
const frame_addr: FrameAddr = switch (operand) {
.load_frame => |frame_addr| frame_addr,
else => frame_addr: {
const frame_index = try self.allocFrameIndex(FrameAlloc.initType(src_ty, self.target.*));
try self.genSetMem(.{ .frame = frame_index }, 0, src_ty, operand);
break :frame_addr .{ .index = frame_index };
},
};
try self.asmMemory(
.{ .f_, .ld },
Memory.sib(Memory.PtrSize.fromSize(src_abi_size), .{
.base = .{ .frame = frame_addr.index },
.disp = frame_addr.off,
const src_mcv = try self.resolveInst(ty_op.operand);
const src_reg = if (src_mcv.isRegister())
src_mcv.getReg().?
else
try self.copyToTmpRegister(src_ty, src_mcv);
const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
defer self.register_manager.unlockReg(src_lock);
const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty));
const dst_mcv = MCValue{ .register = dst_reg };
const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
defer self.register_manager.unlockReg(dst_lock);
try self.asmRegisterRegister(
if (@as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag()) {
.Float => switch (src_ty.floatBits(self.target.*)) {
32 => if (self.hasFeature(.avx)) .{ .v_, .cvttss2si } else .{ ._, .cvttss2si },
64 => if (self.hasFeature(.avx)) .{ .v_, .cvttsd2si } else .{ ._, .cvttsd2si },
16, 80, 128 => null,
else => unreachable,
},
else => null,
})) |tag| tag else return self.fail("TODO implement airFloatToInt from {} to {}", .{
src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
}),
registerAlias(dst_reg, dst_size),
src_reg.to128(),
);
// convert
const stack_dst = try self.allocRegOrMem(inst, false);
try self.asmMemory(
.{ .f_p, .istt },
Memory.sib(Memory.PtrSize.fromSize(dst_abi_size), .{
.base = .{ .frame = stack_dst.load_frame.index },
.disp = stack_dst.load_frame.off,
}),
);
if (dst_bits < dst_size * 8) try self.truncateRegister(dst_ty, dst_reg);
return self.finishAir(inst, stack_dst, .{ ty_op.operand, .none, .none });
return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
}
fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
@ -10997,13 +11000,13 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
reg.to64()
else
unreachable,
.floating_point => if (size_bytes <= 16)
.segment, .x87, .mmx => unreachable,
.sse => if (size_bytes <= 16)
reg.to128()
else if (size_bytes <= 32)
reg.to256()
else
unreachable,
.segment => unreachable,
};
}

View File

@ -233,7 +233,6 @@ pub const Mnemonic = enum {
cmpxchg, cmpxchg8b, cmpxchg16b,
cqo, cwd, cwde,
div,
fisttp, fld,
idiv, imul, int3,
ja, jae, jb, jbe, jc, jrcxz, je, jg, jge, jl, jle, jna, jnae, jnb, jnbe,
jnc, jne, jng, jnge, jnl, jnle, jno, jnp, jns, jnz, jo, jp, jpe, jpo, js, jz,
@ -259,6 +258,8 @@ pub const Mnemonic = enum {
@"test", tzcnt,
ud2,
xadd, xchg, xor,
// X87
fisttp, fld,
// MMX
movd,
// SSE
@ -266,7 +267,7 @@ pub const Mnemonic = enum {
andps,
andnps,
cmpss,
cvtsi2ss,
cvtpi2ps, cvtps2pi, cvtsi2ss, cvtss2si, cvttps2pi, cvttss2si,
divps, divss,
maxps, maxss,
minps, minss,
@ -285,7 +286,9 @@ pub const Mnemonic = enum {
andpd,
andnpd,
//cmpsd,
cvtsd2ss, cvtsi2sd, cvtss2sd,
cvtdq2pd, cvtdq2ps, cvtpd2dq, cvtpd2pi, cvtpd2ps, cvtpi2pd,
cvtps2dq, cvtps2pd, cvtsd2si, cvtsd2ss, cvtsi2sd, cvtss2sd,
cvttpd2dq, cvttpd2pi, cvttps2dq, cvttsd2si,
divpd, divsd,
maxpd, maxsd,
minpd, minsd,
@ -314,7 +317,10 @@ pub const Mnemonic = enum {
// AVX
vaddpd, vaddps, vaddsd, vaddss,
vbroadcastf128, vbroadcastsd, vbroadcastss,
vcvtsd2ss, vcvtsi2sd, vcvtsi2ss, vcvtss2sd,
vcvtdq2pd, vcvtdq2ps, vcvtpd2dq, vcvtpd2ps,
vcvtps2dq, vcvtps2pd, vcvtsd2si, vcvtsd2ss,
vcvtsi2sd, vcvtsi2ss, vcvtss2sd, vcvtss2si,
vcvttpd2dq, vcvttps2dq, vcvttsd2si, vcvttss2si,
vdivpd, vdivps, vdivsd, vdivss,
vextractf128, vextractps,
vinsertf128, vinsertps,
@ -377,80 +383,84 @@ pub const Op = enum {
m,
moffs,
sreg,
st, mm, mm_m64,
xmm, xmm_m32, xmm_m64, xmm_m128,
ymm, ymm_m256,
// zig fmt: on
pub fn fromOperand(operand: Instruction.Operand) Op {
switch (operand) {
.none => return .none,
return switch (operand) {
.none => .none,
.reg => |reg| {
switch (reg.class()) {
.segment => return .sreg,
.floating_point => return switch (reg.bitSize()) {
128 => .xmm,
256 => .ymm,
.reg => |reg| switch (reg.class()) {
.general_purpose => if (reg.to64() == .rax)
switch (reg) {
.al => .al,
.ax => .ax,
.eax => .eax,
.rax => .rax,
else => unreachable,
},
.general_purpose => {
if (reg.to64() == .rax) return switch (reg) {
.al => .al,
.ax => .ax,
.eax => .eax,
.rax => .rax,
else => unreachable,
};
if (reg == .cl) return .cl;
return switch (reg.bitSize()) {
8 => .r8,
16 => .r16,
32 => .r32,
64 => .r64,
else => unreachable,
};
},
}
},
.mem => |mem| switch (mem) {
.moffs => return .moffs,
.sib, .rip => {
const bit_size = mem.bitSize();
return switch (bit_size) {
8 => .m8,
16 => .m16,
32 => .m32,
64 => .m64,
80 => .m80,
128 => .m128,
256 => .m256,
else => unreachable,
};
}
else if (reg == .cl)
.cl
else switch (reg.bitSize()) {
8 => .r8,
16 => .r16,
32 => .r32,
64 => .r64,
else => unreachable,
},
.segment => .sreg,
.x87 => .st,
.mmx => .mm,
.sse => switch (reg.bitSize()) {
128 => .xmm,
256 => .ymm,
else => unreachable,
},
},
.imm => |imm| {
switch (imm) {
.signed => |x| {
if (x == 1) return .unity;
if (math.cast(i8, x)) |_| return .imm8s;
if (math.cast(i16, x)) |_| return .imm16s;
return .imm32s;
},
.unsigned => |x| {
if (x == 1) return .unity;
if (math.cast(i8, x)) |_| return .imm8s;
if (math.cast(u8, x)) |_| return .imm8;
if (math.cast(i16, x)) |_| return .imm16s;
if (math.cast(u16, x)) |_| return .imm16;
if (math.cast(i32, x)) |_| return .imm32s;
if (math.cast(u32, x)) |_| return .imm32;
return .imm64;
},
}
.mem => |mem| switch (mem) {
.moffs => .moffs,
.sib, .rip => switch (mem.bitSize()) {
8 => .m8,
16 => .m16,
32 => .m32,
64 => .m64,
80 => .m80,
128 => .m128,
256 => .m256,
else => unreachable,
},
},
}
.imm => |imm| switch (imm) {
.signed => |x| if (x == 1)
.unity
else if (math.cast(i8, x)) |_|
.imm8s
else if (math.cast(i16, x)) |_|
.imm16s
else
.imm32s,
.unsigned => |x| if (x == 1)
.unity
else if (math.cast(i8, x)) |_|
.imm8s
else if (math.cast(u8, x)) |_|
.imm8
else if (math.cast(i16, x)) |_|
.imm16s
else if (math.cast(u16, x)) |_|
.imm16
else if (math.cast(i32, x)) |_|
.imm32s
else if (math.cast(u32, x)) |_|
.imm32
else
.imm64,
},
};
}
pub fn immBitSize(op: Op) u64 {
@ -460,6 +470,7 @@ pub const Op = enum {
.ax, .r16, .rm16 => unreachable,
.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,
.ymm, .ymm_m256 => unreachable,
.m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable,
@ -480,7 +491,8 @@ pub const Op = enum {
.al, .cl, .r8, .rm8 => 8,
.ax, .r16, .rm16 => 16,
.eax, .r32, .rm32, .r32_m8, .r32_m16 => 32,
.rax, .r64, .rm64, .r64_m16 => 64,
.rax, .r64, .rm64, .r64_m16, .mm, .mm_m64 => 64,
.st => 80,
.xmm, .xmm_m32, .xmm_m64, .xmm_m128 => 128,
.ymm, .ymm_m256 => 256,
};
@ -491,11 +503,11 @@ 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, .xmm, .ymm => unreachable,
.al, .cl, .r8, .ax, .r16, .eax, .r32, .rax, .r64, .st, .mm, .xmm, .ymm => unreachable,
.m8, .rm8, .r32_m8 => 8,
.m16, .rm16, .r32_m16, .r64_m16 => 16,
.m32, .rm32, .xmm_m32 => 32,
.m64, .rm64, .xmm_m64 => 64,
.m64, .rm64, .mm_m64, .xmm_m64 => 64,
.m80 => 80,
.m128, .xmm_m128 => 128,
.m256, .ymm_m256 => 256,
@ -522,6 +534,7 @@ pub const Op = enum {
.r8, .r16, .r32, .r64,
.rm8, .rm16, .rm32, .rm64,
.r32_m8, .r32_m16, .r64_m16,
.st, .mm, .mm_m64,
.xmm, .xmm_m32, .xmm_m64, .xmm_m128,
.ymm, .ymm_m256,
=> true,
@ -550,6 +563,7 @@ pub const Op = enum {
.r32_m8, .r32_m16, .r64_m16,
.m8, .m16, .m32, .m64, .m80, .m128, .m256,
.m,
.mm_m64,
.xmm_m32, .xmm_m64, .xmm_m128,
.ymm_m256,
=> true,
@ -573,8 +587,10 @@ pub const Op = enum {
.rm8, .rm16, .rm32, .rm64 => .general_purpose,
.r32_m8, .r32_m16, .r64_m16 => .general_purpose,
.sreg => .segment,
.xmm, .xmm_m32, .xmm_m64, .xmm_m128 => .floating_point,
.ymm, .ymm_m256 => .floating_point,
.st => .x87,
.mm, .mm_m64 => .mmx,
.xmm, .xmm_m32, .xmm_m64, .xmm_m128 => .sse,
.ymm, .ymm_m256 => .sse,
};
}
@ -695,6 +711,7 @@ pub const Feature = enum {
f16c,
fma,
lzcnt,
movbe,
popcnt,
sse,
sse2,
@ -717,7 +734,7 @@ fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Op
}
const mnemonic_to_encodings_map = init: {
@setEvalBranchQuota(20_000);
@setEvalBranchQuota(25_000);
const encodings = @import("encodings.zig");
var entries = encodings.table;
std.sort.sort(encodings.Entry, &entries, {}, struct {

View File

@ -439,8 +439,21 @@ pub const Inst = struct {
/// Bitwise logical and not of packed single-precision floating-point values
/// Bitwise logical and not of packed double-precision floating-point values
andn,
/// Convert packed doubleword integers to packed single-precision floating-point values
/// Convert packed doubleword integers to packed double-precision floating-point values
cvtpi2,
/// Convert packed single-precision floating-point values to packed doubleword integers
cvtps2pi,
/// Convert doubleword integer to scalar single-precision floating-point value
cvtsi2ss,
/// Convert doubleword integer to scalar double-precision floating-point value
cvtsi2,
/// Convert scalar single-precision floating-point value to doubleword integer
cvtss2si,
/// Convert with truncation packed single-precision floating-point values to packed doubleword integers
cvttps2pi,
/// Convert with truncation scalar single-precision floating-point value to doubleword integer
cvttss2si,
/// Maximum of packed single-precision floating-point values
/// Maximum of scalar single-precision floating-point values
/// Maximum of packed double-precision floating-point values
@ -486,12 +499,33 @@ pub const Inst = struct {
/// Unpack and interleave low packed double-precision floating-point values
unpckl,
/// Convert packed doubleword integers to packed single-precision floating-point values
/// Convert packed doubleword integers to packed double-precision floating-point values
cvtdq2,
/// Convert packed double-precision floating-point values to packed doubleword integers
cvtpd2dq,
/// Convert packed double-precision floating-point values to packed doubleword integers
cvtpd2pi,
/// Convert packed double-precision floating-point values to packed single-precision floating-point values
cvtpd2,
/// Convert packed single-precision floating-point values to packed doubleword integers
cvtps2dq,
/// Convert packed single-precision floating-point values to packed double-precision floating-point values
cvtps2,
/// Convert scalar double-precision floating-point value to doubleword integer
cvtsd2si,
/// Convert scalar double-precision floating-point value to scalar single-precision floating-point value
cvtsd2ss,
/// Convert doubleword integer to scalar double-precision floating-point value
cvtsi2sd,
cvtsd2,
/// Convert scalar single-precision floating-point value to scalar double-precision floating-point value
cvtss2sd,
cvtss2,
/// Convert with truncation packed double-precision floating-point values to packed doubleword integers
cvttpd2dq,
/// Convert with truncation packed double-precision floating-point values to packed doubleword integers
cvttpd2pi,
/// Convert with truncation packed single-precision floating-point values to packed doubleword integers
cvttps2dq,
/// Convert with truncation scalar double-precision floating-point value to doubleword integer
cvttsd2si,
/// Packed interleave shuffle of quadruplets of single-precision floating-point values
/// Packed interleave shuffle of pairs of double-precision floating-point values
shuf,
@ -542,7 +576,7 @@ pub const Inst = struct {
broadcast,
/// Convert 16-bit floating-point values to single-precision floating-point values
cvtph2ps,
cvtph2,
/// Convert single-precision floating-point values to 16-bit floating-point values
cvtps2ph,

View File

@ -175,15 +175,21 @@ pub const Register = enum(u7) {
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
st0, st1, st2, st3, st4, st5, st6, st7,
es, cs, ss, ds, fs, gs,
none,
// zig fmt: on
pub const Class = enum(u2) {
pub const Class = enum {
general_purpose,
floating_point,
segment,
x87,
mmx,
sse,
};
pub fn class(reg: Register) Class {
@ -195,8 +201,10 @@ pub const Register = enum(u7) {
@enumToInt(Register.al) ... @enumToInt(Register.r15b) => .general_purpose,
@enumToInt(Register.ah) ... @enumToInt(Register.bh) => .general_purpose,
@enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => .floating_point,
@enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => .floating_point,
@enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => .sse,
@enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => .sse,
@enumToInt(Register.mm0) ... @enumToInt(Register.mm7) => .mmx,
@enumToInt(Register.st0) ... @enumToInt(Register.st7) => .x87,
@enumToInt(Register.es) ... @enumToInt(Register.gs) => .segment,
@ -216,8 +224,10 @@ pub const Register = enum(u7) {
@enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => @enumToInt(Register.ymm0) - 16,
@enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => @enumToInt(Register.xmm0) - 16,
@enumToInt(Register.mm0) ... @enumToInt(Register.mm7) => @enumToInt(Register.mm0) - 32,
@enumToInt(Register.st0) ... @enumToInt(Register.st7) => @enumToInt(Register.st0) - 40,
@enumToInt(Register.es) ... @enumToInt(Register.gs) => @enumToInt(Register.es) - 32,
@enumToInt(Register.es) ... @enumToInt(Register.gs) => @enumToInt(Register.es) - 48,
else => unreachable,
// zig fmt: on
@ -236,6 +246,8 @@ pub const Register = enum(u7) {
@enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => 256,
@enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => 128,
@enumToInt(Register.mm0) ... @enumToInt(Register.mm7) => 64,
@enumToInt(Register.st0) ... @enumToInt(Register.st7) => 80,
@enumToInt(Register.es) ... @enumToInt(Register.gs) => 16,
@ -271,6 +283,8 @@ pub const Register = enum(u7) {
@enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => @enumToInt(Register.ymm0),
@enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => @enumToInt(Register.xmm0),
@enumToInt(Register.mm0) ... @enumToInt(Register.mm7) => @enumToInt(Register.mm0),
@enumToInt(Register.st0) ... @enumToInt(Register.st7) => @enumToInt(Register.st0),
@enumToInt(Register.es) ... @enumToInt(Register.gs) => @enumToInt(Register.es),
@ -326,8 +340,8 @@ pub const Register = enum(u7) {
return @intToEnum(Register, @enumToInt(reg) - reg.gpBase() + @enumToInt(Register.al));
}
fn fpBase(reg: Register) u7 {
assert(reg.class() == .floating_point);
fn sseBase(reg: Register) u7 {
assert(reg.class() == .sse);
return switch (@enumToInt(reg)) {
@enumToInt(Register.ymm0)...@enumToInt(Register.ymm15) => @enumToInt(Register.ymm0),
@enumToInt(Register.xmm0)...@enumToInt(Register.xmm15) => @enumToInt(Register.xmm0),
@ -336,49 +350,24 @@ pub const Register = enum(u7) {
}
pub fn to256(reg: Register) Register {
return @intToEnum(Register, @enumToInt(reg) - reg.fpBase() + @enumToInt(Register.ymm0));
return @intToEnum(Register, @enumToInt(reg) - reg.sseBase() + @enumToInt(Register.ymm0));
}
pub fn to128(reg: Register) Register {
return @intToEnum(Register, @enumToInt(reg) - reg.fpBase() + @enumToInt(Register.xmm0));
return @intToEnum(Register, @enumToInt(reg) - reg.sseBase() + @enumToInt(Register.xmm0));
}
pub fn dwarfLocOp(reg: Register) u8 {
/// DWARF register encoding
pub fn dwarfNum(reg: Register) u6 {
return switch (reg.class()) {
.general_purpose => switch (reg.to64()) {
.rax => DW.OP.reg0,
.rdx => DW.OP.reg1,
.rcx => DW.OP.reg2,
.rbx => DW.OP.reg3,
.rsi => DW.OP.reg4,
.rdi => DW.OP.reg5,
.rbp => DW.OP.reg6,
.rsp => DW.OP.reg7,
else => @intCast(u8, @enumToInt(reg) - reg.gpBase()) + DW.OP.reg0,
},
.floating_point => @intCast(u8, @enumToInt(reg) - reg.fpBase()) + DW.OP.reg17,
else => unreachable,
};
}
/// DWARF encodings that push a value onto the DWARF stack that is either
/// the contents of a register or the result of adding the contents a given
/// register to a given signed offset.
pub fn dwarfLocOpDeref(reg: Register) u8 {
return switch (reg.class()) {
.general_purpose => switch (reg.to64()) {
.rax => DW.OP.breg0,
.rdx => DW.OP.breg1,
.rcx => DW.OP.breg2,
.rbx => DW.OP.breg3,
.rsi => DW.OP.breg4,
.rdi => DW.OP.breg5,
.rbp => DW.OP.breg6,
.rsp => DW.OP.breg7,
else => @intCast(u8, @enumToInt(reg) - reg.gpBase()) + DW.OP.breg0,
},
.floating_point => @intCast(u8, @enumToInt(reg) - reg.fpBase()) + DW.OP.breg17,
else => unreachable,
.general_purpose => if (reg.isExtended())
reg.enc()
else
@truncate(u3, @as(u24, 0o54673120) >> @as(u5, reg.enc()) * 3),
.sse => 17 + @as(u6, reg.enc()),
.x87 => 33 + @as(u6, reg.enc()),
.mmx => 41 + @as(u6, reg.enc()),
.segment => 50 + @as(u6, reg.enc()),
};
}
};
@ -392,6 +381,8 @@ test "Register id - different classes" {
try expect(Register.ymm0.id() == 0b10000);
try expect(Register.ymm0.id() != Register.rax.id());
try expect(Register.xmm0.id() == Register.ymm0.id());
try expect(Register.xmm0.id() != Register.mm0.id());
try expect(Register.mm0.id() != Register.st0.id());
try expect(Register.es.id() == 0b100000);
}
@ -407,7 +398,9 @@ test "Register enc - different classes" {
test "Register classes" {
try expect(Register.r11.class() == .general_purpose);
try expect(Register.ymm11.class() == .floating_point);
try expect(Register.ymm11.class() == .sse);
try expect(Register.mm3.class() == .mmx);
try expect(Register.st3.class() == .x87);
try expect(Register.fs.class() == .segment);
}

View File

@ -272,14 +272,6 @@ pub const table = [_]Entry{
.{ .div, .m, &.{ .rm32 }, &.{ 0xf7 }, 6, .none, .none },
.{ .div, .m, &.{ .rm64 }, &.{ 0xf7 }, 6, .long, .none },
.{ .fisttp, .m, &.{ .m16 }, &.{ 0xdf }, 1, .none, .x87 },
.{ .fisttp, .m, &.{ .m32 }, &.{ 0xdb }, 1, .none, .x87 },
.{ .fisttp, .m, &.{ .m64 }, &.{ 0xdd }, 1, .none, .x87 },
.{ .fld, .m, &.{ .m32 }, &.{ 0xd9 }, 0, .none, .x87 },
.{ .fld, .m, &.{ .m64 }, &.{ 0xdd }, 0, .none, .x87 },
.{ .fld, .m, &.{ .m80 }, &.{ 0xdb }, 5, .none, .x87 },
.{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .none, .none },
.{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .rex, .none },
.{ .idiv, .m, &.{ .rm16 }, &.{ 0xf7 }, 7, .short, .none },
@ -395,12 +387,12 @@ pub const table = [_]Entry{
.{ .mov, .mi, &.{ .rm32, .imm32 }, &.{ 0xc7 }, 0, .none, .none },
.{ .mov, .mi, &.{ .rm64, .imm32s }, &.{ 0xc7 }, 0, .long, .none },
.{ .movbe, .rm, &.{ .r16, .m16 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .short, .none },
.{ .movbe, .rm, &.{ .r32, .m32 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .none, .none },
.{ .movbe, .rm, &.{ .r64, .m64 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .long, .none },
.{ .movbe, .mr, &.{ .m16, .r16 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .short, .none },
.{ .movbe, .mr, &.{ .m32, .r32 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none, .none },
.{ .movbe, .mr, &.{ .m64, .r64 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .long, .none },
.{ .movbe, .rm, &.{ .r16, .m16 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .short, .movbe },
.{ .movbe, .rm, &.{ .r32, .m32 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .none, .movbe },
.{ .movbe, .rm, &.{ .r64, .m64 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .long, .movbe },
.{ .movbe, .mr, &.{ .m16, .r16 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .short, .movbe },
.{ .movbe, .mr, &.{ .m32, .r32 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none, .movbe },
.{ .movbe, .mr, &.{ .m64, .r64 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .long, .movbe },
.{ .movs, .np, &.{ .m8, .m8 }, &.{ 0xa4 }, 0, .none, .none },
.{ .movs, .np, &.{ .m16, .m16 }, &.{ 0xa5 }, 0, .short, .none },
@ -836,6 +828,15 @@ pub const table = [_]Entry{
.{ .xor, .rm, &.{ .r32, .rm32 }, &.{ 0x33 }, 0, .none, .none },
.{ .xor, .rm, &.{ .r64, .rm64 }, &.{ 0x33 }, 0, .long, .none },
// X87
.{ .fisttp, .m, &.{ .m16 }, &.{ 0xdf }, 1, .none, .x87 },
.{ .fisttp, .m, &.{ .m32 }, &.{ 0xdb }, 1, .none, .x87 },
.{ .fisttp, .m, &.{ .m64 }, &.{ 0xdd }, 1, .none, .x87 },
.{ .fld, .m, &.{ .m32 }, &.{ 0xd9 }, 0, .none, .x87 },
.{ .fld, .m, &.{ .m64 }, &.{ 0xdd }, 0, .none, .x87 },
.{ .fld, .m, &.{ .m80 }, &.{ 0xdb }, 5, .none, .x87 },
// SSE
.{ .addps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x58 }, 0, .none, .sse },
@ -847,9 +848,21 @@ pub const table = [_]Entry{
.{ .cmpss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0xf3, 0x0f, 0xc2 }, 0, .none, .sse },
.{ .cvtpi2ps, .rm, &.{ .xmm, .mm_m64 }, &.{ 0x0f, 0x2a }, 0, .none, .sse },
.{ .cvtps2pi, .rm, &.{ .mm, .xmm_m64 }, &.{ 0x0f, 0x2d }, 0, .none, .sse },
.{ .cvtsi2ss, .rm, &.{ .xmm, .rm32 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .none, .sse },
.{ .cvtsi2ss, .rm, &.{ .xmm, .rm64 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .long, .sse },
.{ .cvtss2si, .rm, &.{ .r32, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2d }, 0, .none, .sse },
.{ .cvtss2si, .rm, &.{ .r64, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2d }, 0, .long, .sse },
.{ .cvttps2pi, .rm, &.{ .mm, .xmm_m64 }, &.{ 0x0f, 0x2c }, 0, .none, .sse },
.{ .cvttss2si, .rm, &.{ .r32, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2c }, 0, .none, .sse },
.{ .cvttss2si, .rm, &.{ .r64, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2c }, 0, .long, .sse },
.{ .divps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5e }, 0, .none, .sse },
.{ .divss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5e }, 0, .none, .sse },
@ -906,6 +919,25 @@ pub const table = [_]Entry{
.{ .cmpsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0xf2, 0x0f, 0xc2 }, 0, .none, .sse2 },
.{ .cvtdq2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0xe6 }, 0, .none, .sse2 },
.{ .cvtdq2ps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5b }, 0, .none, .sse2 },
.{ .cvtpd2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf2, 0x0f, 0xe6 }, 0, .none, .sse2 },
.{ .cvtpd2pi, .rm, &.{ .mm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x2d }, 0, .none, .sse2 },
.{ .cvtpd2ps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5a }, 0, .none, .sse2 },
.{ .cvtpi2pd, .rm, &.{ .xmm, .mm_m64 }, &.{ 0x66, 0x0f, 0x2a }, 0, .none, .sse2 },
.{ .cvtps2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5b }, 0, .none, .sse2 },
.{ .cvtps2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x0f, 0x5a }, 0, .none, .sse2 },
.{ .cvtsd2si, .rm, &.{ .r32, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2d }, 0, .none, .sse2 },
.{ .cvtsd2si, .rm, &.{ .r64, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2d }, 0, .long, .sse2 },
.{ .cvtsd2ss, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .none, .sse2 },
.{ .cvtsi2sd, .rm, &.{ .xmm, .rm32 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .none, .sse2 },
@ -913,6 +945,15 @@ pub const table = [_]Entry{
.{ .cvtss2sd, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5a }, 0, .none, .sse2 },
.{ .cvttpd2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xe6 }, 0, .none, .sse2 },
.{ .cvttpd2pi, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x2c }, 0, .none, .sse2 },
.{ .cvttps2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0x5b }, 0, .none, .sse2 },
.{ .cvttsd2si, .rm, &.{ .r32, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2c }, 0, .none, .sse2 },
.{ .cvttsd2si, .rm, &.{ .r64, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2c }, 0, .long, .sse2 },
.{ .divpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5e }, 0, .none, .sse2 },
.{ .divsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5e }, 0, .none, .sse2 },
@ -1034,15 +1075,51 @@ pub const table = [_]Entry{
.{ .vbroadcastsd, .rm, &.{ .ymm, .m64 }, &.{ 0x66, 0x0f, 0x38, 0x19 }, 0, .vex_256_w0, .avx },
.{ .vbroadcastf128, .rm, &.{ .ymm, .m128 }, &.{ 0x66, 0x0f, 0x38, 0x1a }, 0, .vex_256_w0, .avx },
.{ .vcvtdq2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0xe6 }, 0, .vex_128_wig, .avx },
.{ .vcvtdq2pd, .rm, &.{ .ymm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0xe6 }, 0, .vex_256_wig, .avx },
.{ .vcvtdq2ps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5b }, 0, .vex_128_wig, .avx },
.{ .vcvtdq2ps, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x0f, 0x5b }, 0, .vex_256_wig, .avx },
.{ .vcvtpd2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf2, 0x0f, 0xe6 }, 0, .vex_128_wig, .avx },
.{ .vcvtpd2dq, .rm, &.{ .xmm, .ymm_m256 }, &.{ 0xf2, 0x0f, 0xe6 }, 0, .vex_256_wig, .avx },
.{ .vcvtpd2ps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5a }, 0, .vex_128_wig, .avx },
.{ .vcvtpd2ps, .rm, &.{ .xmm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5a }, 0, .vex_256_wig, .avx },
.{ .vcvtps2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5b }, 0, .vex_128_wig, .avx },
.{ .vcvtps2dq, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5b }, 0, .vex_256_wig, .avx },
.{ .vcvtps2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x0f, 0x5a }, 0, .vex_128_wig, .avx },
.{ .vcvtps2pd, .rm, &.{ .ymm, .xmm_m128 }, &.{ 0x0f, 0x5a }, 0, .vex_256_wig, .avx },
.{ .vcvtsd2si, .rm, &.{ .r32, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2d }, 0, .vex_lig_w0, .sse2 },
.{ .vcvtsd2si, .rm, &.{ .r64, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2d }, 0, .vex_lig_w1, .sse2 },
.{ .vcvtsd2ss, .rvm, &.{ .xmm, .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .vex_lig_wig, .avx },
.{ .vcvtsi2sd, .rvm, &.{ .xmm, .xmm, .rm32 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w0, .avx },
.{ .vcvtsi2sd, .rvm, &.{ .xmm, .xmm, .rm64 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w1, .avx },
.{ .vcvtsi2ss, .rvm, &.{ .xmm, .xmm, .rm32 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w0, .avx },
.{ .vcvtsi2ss, .rvm, &.{ .xmm, .xmm, .rm64 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w1, .avx },
.{ .vcvtsi2ss, .rvm, &.{ .xmm, .xmm, .rm32 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .vex_lig_w0, .avx },
.{ .vcvtsi2ss, .rvm, &.{ .xmm, .xmm, .rm64 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .vex_lig_w1, .avx },
.{ .vcvtss2sd, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .vex_lig_wig, .avx },
.{ .vcvtss2sd, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5a }, 0, .vex_lig_wig, .avx },
.{ .vcvtss2si, .rm, &.{ .r32, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2d }, 0, .vex_lig_w0, .avx },
.{ .vcvtss2si, .rm, &.{ .r64, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2d }, 0, .vex_lig_w1, .avx },
.{ .vcvttpd2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xe6 }, 0, .vex_128_wig, .avx },
.{ .vcvttpd2dq, .rm, &.{ .xmm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xe6 }, 0, .vex_256_wig, .avx },
.{ .vcvttps2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0x5b }, 0, .vex_128_wig, .avx },
.{ .vcvttps2dq, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0xf3, 0x0f, 0x5b }, 0, .vex_256_wig, .avx },
.{ .vcvttsd2si, .rm, &.{ .r32, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2c }, 0, .vex_lig_w0, .sse2 },
.{ .vcvttsd2si, .rm, &.{ .r64, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2c }, 0, .vex_lig_w1, .sse2 },
.{ .vcvttss2si, .rm, &.{ .r32, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2c }, 0, .vex_lig_w0, .avx },
.{ .vcvttss2si, .rm, &.{ .r64, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2c }, 0, .vex_lig_w1, .avx },
.{ .vdivpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5e }, 0, .vex_128_wig, .avx },
.{ .vdivpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5e }, 0, .vex_256_wig, .avx },

View File

@ -608,23 +608,44 @@ pub const DeclState = struct {
switch (loc) {
.register => |reg| {
try dbg_info.ensureUnusedCapacity(3);
try dbg_info.ensureUnusedCapacity(4);
dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));
dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1, // ULEB128 dwarf expression length
reg,
});
// DW.AT.location, DW.FORM.exprloc
var expr_len = std.io.countingWriter(std.io.null_writer);
if (reg < 32) {
expr_len.writer().writeByte(DW.OP.reg0 + reg) catch unreachable;
} else {
expr_len.writer().writeByte(DW.OP.regx) catch unreachable;
leb128.writeULEB128(expr_len.writer(), reg) catch unreachable;
}
leb128.writeULEB128(dbg_info.writer(), expr_len.bytes_written) catch unreachable;
if (reg < 32) {
dbg_info.appendAssumeCapacity(DW.OP.reg0 + reg);
} else {
dbg_info.appendAssumeCapacity(DW.OP.regx);
leb128.writeULEB128(dbg_info.writer(), reg) catch unreachable;
}
},
.stack => |info| {
try dbg_info.ensureUnusedCapacity(8);
try dbg_info.ensureUnusedCapacity(9);
dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));
const fixup = dbg_info.items.len;
dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1, // we will backpatch it after we encode the displacement in LEB128
info.fp_register, // frame pointer
});
// DW.AT.location, DW.FORM.exprloc
var expr_len = std.io.countingWriter(std.io.null_writer);
if (info.fp_register < 32) {
expr_len.writer().writeByte(DW.OP.breg0 + info.fp_register) catch unreachable;
} else {
expr_len.writer().writeByte(DW.OP.bregx) catch unreachable;
leb128.writeULEB128(expr_len.writer(), info.fp_register) catch unreachable;
}
leb128.writeILEB128(expr_len.writer(), info.offset) catch unreachable;
leb128.writeULEB128(dbg_info.writer(), expr_len.bytes_written) catch unreachable;
if (info.fp_register < 32) {
dbg_info.appendAssumeCapacity(DW.OP.breg0 + info.fp_register);
} else {
dbg_info.appendAssumeCapacity(DW.OP.bregx);
leb128.writeULEB128(dbg_info.writer(), info.fp_register) catch unreachable;
}
leb128.writeILEB128(dbg_info.writer(), info.offset) catch unreachable;
dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
},
.wasm_local => |value| {
const leb_size = link.File.Wasm.getULEB128Size(value);
@ -670,22 +691,45 @@ pub const DeclState = struct {
switch (loc) {
.register => |reg| {
try dbg_info.ensureUnusedCapacity(2);
dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1, // ULEB128 dwarf expression length
reg,
});
try dbg_info.ensureUnusedCapacity(4);
dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));
// DW.AT.location, DW.FORM.exprloc
var expr_len = std.io.countingWriter(std.io.null_writer);
if (reg < 32) {
expr_len.writer().writeByte(DW.OP.reg0 + reg) catch unreachable;
} else {
expr_len.writer().writeByte(DW.OP.regx) catch unreachable;
leb128.writeULEB128(expr_len.writer(), reg) catch unreachable;
}
leb128.writeULEB128(dbg_info.writer(), expr_len.bytes_written) catch unreachable;
if (reg < 32) {
dbg_info.appendAssumeCapacity(DW.OP.reg0 + reg);
} else {
dbg_info.appendAssumeCapacity(DW.OP.regx);
leb128.writeULEB128(dbg_info.writer(), reg) catch unreachable;
}
},
.stack => |info| {
try dbg_info.ensureUnusedCapacity(7);
const fixup = dbg_info.items.len;
dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1, // we will backpatch it after we encode the displacement in LEB128
info.fp_register,
});
try dbg_info.ensureUnusedCapacity(9);
dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));
// DW.AT.location, DW.FORM.exprloc
var expr_len = std.io.countingWriter(std.io.null_writer);
if (info.fp_register < 32) {
expr_len.writer().writeByte(DW.OP.breg0 + info.fp_register) catch unreachable;
} else {
expr_len.writer().writeByte(DW.OP.bregx) catch unreachable;
leb128.writeULEB128(expr_len.writer(), info.fp_register) catch unreachable;
}
leb128.writeILEB128(expr_len.writer(), info.offset) catch unreachable;
leb128.writeULEB128(dbg_info.writer(), expr_len.bytes_written) catch unreachable;
if (info.fp_register < 32) {
dbg_info.appendAssumeCapacity(DW.OP.breg0 + info.fp_register);
} else {
dbg_info.appendAssumeCapacity(DW.OP.bregx);
leb128.writeULEB128(dbg_info.writer(), info.fp_register) catch unreachable;
}
leb128.writeILEB128(dbg_info.writer(), info.offset) catch unreachable;
dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
},
.wasm_local => |value| {

View File

@ -153,7 +153,6 @@ test "@intToFloat(f80)" {
test "@floatToInt" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;