authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-13 18:06:16-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-15 03:07:51-04:00
logb6d61028508c5b1e1961a124bc17d4d9bda9686f
tree9b50fbfca9bf08638a44635d7da534284afb684d
parente08eab664861461b0adbe7984881f72b5a36a979

x86_64: reimplement `@floatToInt`


7 files changed, 420 insertions(+), 253 deletions(-)

src/arch/x86_64/CodeGen.zig+92-89
...@@ -2501,12 +2501,12 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -2501,12 +2501,12 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
2501 }2501 }
2502 } else if (src_bits == 64 and dst_bits == 32) {2502 } else if (src_bits == 64 and dst_bits == 32) {
2503 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(2503 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
2504 .{ .v_, .cvtsd2ss },2504 .{ .v_ss, .cvtsd2 },
2505 dst_reg,2505 dst_reg,
2506 dst_reg,2506 dst_reg,
2507 src_mcv.mem(.qword),2507 src_mcv.mem(.qword),
2508 ) else try self.asmRegisterRegisterRegister(2508 ) else try self.asmRegisterRegisterRegister(
2509 .{ .v_, .cvtsd2ss },2509 .{ .v_ss, .cvtsd2 },
2510 dst_reg,2510 dst_reg,
2511 dst_reg,2511 dst_reg,
2512 (if (src_mcv.isRegister())2512 (if (src_mcv.isRegister())
...@@ -2514,11 +2514,11 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -2514,11 +2514,11 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
2514 else2514 else
2515 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),2515 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2516 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(2516 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2517 .{ ._, .cvtsd2ss },2517 .{ ._ss, .cvtsd2 },
2518 dst_reg,2518 dst_reg,
2519 src_mcv.mem(.qword),2519 src_mcv.mem(.qword),
2520 ) else try self.asmRegisterRegister(2520 ) else try self.asmRegisterRegister(
2521 .{ ._, .cvtsd2ss },2521 .{ ._ss, .cvtsd2 },
2522 dst_reg,2522 dst_reg,
2523 (if (src_mcv.isRegister())2523 (if (src_mcv.isRegister())
2524 src_mcv.getReg().?2524 src_mcv.getReg().?
...@@ -2552,22 +2552,22 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {...@@ -2552,22 +2552,22 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
2552 src_mcv.getReg().?2552 src_mcv.getReg().?
2553 else2553 else
2554 try self.copyToTmpRegister(src_ty, src_mcv);2554 try self.copyToTmpRegister(src_ty, src_mcv);
2555 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, mat_src_reg.to128());2555 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, mat_src_reg.to128());
2556 switch (dst_bits) {2556 switch (dst_bits) {
2557 32 => {},2557 32 => {},
2558 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),
2559 else => return self.fail("TODO implement airFpext from {} to {}", .{2559 else => return self.fail("TODO implement airFpext from {} to {}", .{
2560 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),2560 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
2561 }),2561 }),
2562 }2562 }
2563 } else if (src_bits == 32 and dst_bits == 64) {2563 } else if (src_bits == 32 and dst_bits == 64) {
2564 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(2564 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
2565 .{ .v_, .cvtss2sd },2565 .{ .v_sd, .cvtss2 },
2566 dst_reg,2566 dst_reg,
2567 dst_reg,2567 dst_reg,
2568 src_mcv.mem(.dword),2568 src_mcv.mem(.dword),
2569 ) else try self.asmRegisterRegisterRegister(2569 ) else try self.asmRegisterRegisterRegister(
2570 .{ .v_, .cvtss2sd },2570 .{ .v_sd, .cvtss2 },
2571 dst_reg,2571 dst_reg,
2572 dst_reg,2572 dst_reg,
2573 (if (src_mcv.isRegister())2573 (if (src_mcv.isRegister())
...@@ -2575,11 +2575,11 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {...@@ -2575,11 +2575,11 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
2575 else2575 else
2576 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),2576 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2577 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(2577 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2578 .{ ._, .cvtss2sd },2578 .{ ._sd, .cvtss2 },
2579 dst_reg,2579 dst_reg,
2580 src_mcv.mem(.dword),2580 src_mcv.mem(.dword),
2581 ) else try self.asmRegisterRegister(2581 ) else try self.asmRegisterRegister(
2582 .{ ._, .cvtss2sd },2582 .{ ._sd, .cvtss2 },
2583 dst_reg,2583 dst_reg,
2584 (if (src_mcv.isRegister())2584 (if (src_mcv.isRegister())
2585 src_mcv.getReg().?2585 src_mcv.getReg().?
...@@ -4789,7 +4789,6 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4...@@ -4789,7 +4789,6 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
4789 })) |tag| tag else return self.fail("TODO implement genRound for {}", .{4789 })) |tag| tag else return self.fail("TODO implement genRound for {}", .{
4790 ty.fmt(self.bin_file.options.module.?),4790 ty.fmt(self.bin_file.options.module.?),
4791 });4791 });
4792
4793 const abi_size = @intCast(u32, ty.abiSize(self.target.*));4792 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
4794 const dst_alias = registerAlias(dst_reg, abi_size);4793 const dst_alias = registerAlias(dst_reg, abi_size);
4795 switch (mir_tag[0]) {4794 switch (mir_tag[0]) {
...@@ -4848,7 +4847,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {...@@ -4848,7 +4847,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
4848 src_mcv.getReg().?4847 src_mcv.getReg().?
4849 else4848 else
4850 try self.copyToTmpRegister(ty, src_mcv);4849 try self.copyToTmpRegister(ty, src_mcv);
4851 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, mat_src_reg.to128());4850 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, mat_src_reg.to128());
4852 try self.asmRegisterRegisterRegister(.{ .v_ss, .sqrt }, dst_reg, dst_reg, dst_reg);4851 try self.asmRegisterRegisterRegister(.{ .v_ss, .sqrt }, dst_reg, dst_reg, dst_reg);
4853 try self.asmRegisterRegisterImmediate(4852 try self.asmRegisterRegisterImmediate(
4854 .{ .v_, .cvtps2ph },4853 .{ .v_, .cvtps2ph },
...@@ -4868,7 +4867,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {...@@ -4868,7 +4867,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
4868 16 => if (self.hasFeature(.f16c)) switch (ty.vectorLen()) {4867 16 => if (self.hasFeature(.f16c)) switch (ty.vectorLen()) {
4869 1 => {4868 1 => {
4870 try self.asmRegisterRegister(4869 try self.asmRegisterRegister(
4871 .{ .v_, .cvtph2ps },4870 .{ .v_ps, .cvtph2 },
4872 dst_reg,4871 dst_reg,
4873 (if (src_mcv.isRegister())4872 (if (src_mcv.isRegister())
4874 src_mcv.getReg().?4873 src_mcv.getReg().?
...@@ -4892,13 +4891,13 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {...@@ -4892,13 +4891,13 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
4892 2...8 => {4891 2...8 => {
4893 const wide_reg = registerAlias(dst_reg, abi_size * 2);4892 const wide_reg = registerAlias(dst_reg, abi_size * 2);
4894 if (src_mcv.isMemory()) try self.asmRegisterMemory(4893 if (src_mcv.isMemory()) try self.asmRegisterMemory(
4895 .{ .v_, .cvtph2ps },4894 .{ .v_ps, .cvtph2 },
4896 wide_reg,4895 wide_reg,
4897 src_mcv.mem(Memory.PtrSize.fromSize(4896 src_mcv.mem(Memory.PtrSize.fromSize(
4898 @intCast(u32, @divExact(wide_reg.bitSize(), 16)),4897 @intCast(u32, @divExact(wide_reg.bitSize(), 16)),
4899 )),4898 )),
4900 ) else try self.asmRegisterRegister(4899 ) else try self.asmRegisterRegister(
4901 .{ .v_, .cvtph2ps },4900 .{ .v_ps, .cvtph2 },
4902 wide_reg,4901 wide_reg,
4903 (if (src_mcv.isRegister())4902 (if (src_mcv.isRegister())
4904 src_mcv.getReg().?4903 src_mcv.getReg().?
...@@ -6347,7 +6346,7 @@ fn genBinOp(...@@ -6347,7 +6346,7 @@ fn genBinOp(
6347 else6346 else
6348 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),6347 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
6349 );6348 );
6350 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, dst_reg);6349 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
6351 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp_reg, dst_reg);6350 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp_reg, dst_reg);
6352 try self.asmRegisterRegisterRegister(6351 try self.asmRegisterRegisterRegister(
6353 switch (air_tag) {6352 switch (air_tag) {
...@@ -6424,7 +6423,7 @@ fn genBinOp(...@@ -6424,7 +6423,7 @@ fn genBinOp(
6424 else6423 else
6425 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),6424 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
6426 );6425 );
6427 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, dst_reg);6426 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
6428 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp_reg, dst_reg);6427 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp_reg, dst_reg);
6429 try self.asmRegisterRegisterRegister(6428 try self.asmRegisterRegisterRegister(
6430 switch (air_tag) {6429 switch (air_tag) {
...@@ -6467,7 +6466,7 @@ fn genBinOp(...@@ -6467,7 +6466,7 @@ fn genBinOp(
6467 else6466 else
6468 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),6467 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
6469 );6468 );
6470 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, dst_reg);6469 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
6471 try self.asmRegisterRegisterRegister(6470 try self.asmRegisterRegisterRegister(
6472 .{ .v_ps, .movhl },6471 .{ .v_ps, .movhl },
6473 tmp_reg,6472 tmp_reg,
...@@ -6501,13 +6500,13 @@ fn genBinOp(...@@ -6501,13 +6500,13 @@ fn genBinOp(
6501 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);6500 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6502 defer self.register_manager.unlockReg(tmp_lock);6501 defer self.register_manager.unlockReg(tmp_lock);
65036502
6504 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg, dst_reg);6503 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
6505 if (src_mcv.isMemory()) try self.asmRegisterMemory(6504 if (src_mcv.isMemory()) try self.asmRegisterMemory(
6506 .{ .v_, .cvtph2ps },6505 .{ .v_ps, .cvtph2 },
6507 tmp_reg,6506 tmp_reg,
6508 src_mcv.mem(.qword),6507 src_mcv.mem(.qword),
6509 ) else try self.asmRegisterRegister(6508 ) else try self.asmRegisterRegister(
6510 .{ .v_, .cvtph2ps },6509 .{ .v_ps, .cvtph2 },
6511 tmp_reg,6510 tmp_reg,
6512 (if (src_mcv.isRegister())6511 (if (src_mcv.isRegister())
6513 src_mcv.getReg().?6512 src_mcv.getReg().?
...@@ -6541,13 +6540,13 @@ fn genBinOp(...@@ -6541,13 +6540,13 @@ fn genBinOp(
6541 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);6540 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6542 defer self.register_manager.unlockReg(tmp_lock);6541 defer self.register_manager.unlockReg(tmp_lock);
65436542
6544 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, dst_reg.to256(), dst_reg);6543 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg.to256(), dst_reg);
6545 if (src_mcv.isMemory()) try self.asmRegisterMemory(6544 if (src_mcv.isMemory()) try self.asmRegisterMemory(
6546 .{ .v_, .cvtph2ps },6545 .{ .v_ps, .cvtph2 },
6547 tmp_reg,6546 tmp_reg,
6548 src_mcv.mem(.xword),6547 src_mcv.mem(.xword),
6549 ) else try self.asmRegisterRegister(6548 ) else try self.asmRegisterRegister(
6550 .{ .v_, .cvtph2ps },6549 .{ .v_ps, .cvtph2 },
6551 tmp_reg,6550 tmp_reg,
6552 (if (src_mcv.isRegister())6551 (if (src_mcv.isRegister())
6553 src_mcv.getReg().?6552 src_mcv.getReg().?
...@@ -7199,13 +7198,13 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void {...@@ -7199,13 +7198,13 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void {
7199 switch (self.debug_output) {7198 switch (self.debug_output) {
7200 .dwarf => |dw| {7199 .dwarf => |dw| {
7201 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {7200 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {
7202 .register => |reg| .{ .register = reg.dwarfLocOp() },7201 .register => |reg| .{ .register = reg.dwarfNum() },
7203 // TODO use a frame index7202 // TODO use a frame index
7204 .load_frame => return,7203 .load_frame => return,
7205 //.stack_offset => |off| .{7204 //.stack_offset => |off| .{
7206 // .stack = .{7205 // .stack = .{
7207 // // TODO handle -fomit-frame-pointer7206 // // TODO handle -fomit-frame-pointer
7208 // .fp_register = Register.rbp.dwarfLocOpDeref(),7207 // .fp_register = Register.rbp.dwarfNum(),
7209 // .offset = -off,7208 // .offset = -off,
7210 // },7209 // },
7211 //},7210 //},
...@@ -7237,11 +7236,11 @@ fn genVarDbgInfo(...@@ -7237,11 +7236,11 @@ fn genVarDbgInfo(
7237 switch (self.debug_output) {7236 switch (self.debug_output) {
7238 .dwarf => |dw| {7237 .dwarf => |dw| {
7239 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {7238 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {
7240 .register => |reg| .{ .register = reg.dwarfLocOp() },7239 .register => |reg| .{ .register = reg.dwarfNum() },
7241 // TODO use a frame index7240 // TODO use a frame index
7242 .load_frame, .lea_frame => return,7241 .load_frame, .lea_frame => return,
7243 //=> |off| .{ .stack = .{7242 //=> |off| .{ .stack = .{
7244 // .fp_register = Register.rbp.dwarfLocOpDeref(),7243 // .fp_register = Register.rbp.dwarfNum(),
7245 // .offset = -off,7244 // .offset = -off,
7246 //} },7245 //} },
7247 .memory => |address| .{ .memory = address },7246 .memory => |address| .{ .memory = address },
...@@ -7595,7 +7594,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -7595,7 +7594,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
7595 else7594 else
7596 try self.copyToTmpRegister(ty, src_mcv)).to128(),7595 try self.copyToTmpRegister(ty, src_mcv)).to128(),
7597 );7596 );
7598 try self.asmRegisterRegister(.{ .v_, .cvtph2ps }, tmp1_reg, tmp1_reg);7597 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, tmp1_reg, tmp1_reg);
7599 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp2_reg, tmp1_reg);7598 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp2_reg, tmp1_reg);
7600 try self.genBinOpMir(.{ ._ss, .ucomi }, ty, tmp1_mcv, tmp2_mcv);7599 try self.genBinOpMir(.{ ._ss, .ucomi }, ty, tmp1_mcv, tmp2_mcv);
7601 } else return self.fail("TODO implement airCmp for {}", .{7600 } 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...@@ -8862,14 +8861,14 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
8862 }8861 }
8863 },8862 },
8864 .register => |src_reg| if (dst_reg.id() != src_reg.id()) try self.asmRegisterRegister(8863 .register => |src_reg| if (dst_reg.id() != src_reg.id()) try self.asmRegisterRegister(
8865 if ((dst_reg.class() == .floating_point) == (src_reg.class() == .floating_point))8864 if ((dst_reg.class() == .sse) == (src_reg.class() == .sse))
8866 switch (ty.zigTypeTag()) {8865 switch (ty.zigTypeTag()) {
8867 else => .{ ._, .mov },8866 else => .{ ._, .mov },
8868 .Float, .Vector => .{ ._ps, .mova },8867 .Float, .Vector => .{ ._ps, .mova },
8869 }8868 }
8870 else switch (abi_size) {8869 else switch (abi_size) {
8871 2 => return try self.asmRegisterRegisterImmediate(8870 2 => return try self.asmRegisterRegisterImmediate(
8872 if (dst_reg.class() == .floating_point) .{ .p_w, .insr } else .{ .p_w, .extr },8871 if (dst_reg.class() == .sse) .{ .p_w, .insr } else .{ .p_w, .extr },
8873 registerAlias(dst_reg, 4),8872 registerAlias(dst_reg, 4),
8874 registerAlias(src_reg, 4),8873 registerAlias(src_reg, 4),
8875 Immediate.u(0),8874 Immediate.u(0),
...@@ -9222,7 +9221,7 @@ fn genInlineMemcpyRegisterRegister(...@@ -9222,7 +9221,7 @@ fn genInlineMemcpyRegisterRegister(
9222 try self.asmMemoryRegister(9221 try self.asmMemoryRegister(
9223 switch (src_reg.class()) {9222 switch (src_reg.class()) {
9224 .general_purpose, .segment => .{ ._, .mov },9223 .general_purpose, .segment => .{ ._, .mov },
9225 .floating_point => .{ ._ss, .mov },9224 .sse => .{ ._ss, .mov },
9226 },9225 },
9227 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = dst_reg, .disp = -offset }),9226 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = dst_reg, .disp = -offset }),
9228 registerAlias(src_reg, abi_size),9227 registerAlias(src_reg, abi_size),
...@@ -9388,10 +9387,10 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {...@@ -9388,10 +9387,10 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
9388 });9387 });
93899388
9390 const src_mcv = try self.resolveInst(ty_op.operand);9389 const src_mcv = try self.resolveInst(ty_op.operand);
9391 const src_reg = switch (src_mcv) {9390 const src_reg = if (src_mcv.isRegister())
9392 .register => |reg| reg,9391 src_mcv.getReg().?
9393 else => try self.copyToTmpRegister(src_ty, src_mcv),9392 else
9394 };9393 try self.copyToTmpRegister(src_ty, src_mcv);
9395 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);9394 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
9396 defer self.register_manager.unlockReg(src_lock);9395 defer self.register_manager.unlockReg(src_lock);
93979396
...@@ -9402,23 +9401,23 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {...@@ -9402,23 +9401,23 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
9402 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);9401 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
9403 defer self.register_manager.unlockReg(dst_lock);9402 defer self.register_manager.unlockReg(dst_lock);
94049403
9405 try self.asmRegisterRegister(switch (dst_ty.floatBits(self.target.*)) {9404 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_ty.zigTypeTag()) {
9406 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse))9405 .Float => switch (dst_ty.floatBits(self.target.*)) {
9407 .{ ._, .cvtsi2ss }9406 32 => if (self.hasFeature(.avx)) .{ .v_ss, .cvtsi2 } else .{ ._ss, .cvtsi2 },
9408 else9407 64 => if (self.hasFeature(.avx)) .{ .v_sd, .cvtsi2 } else .{ ._sd, .cvtsi2 },
9409 return self.fail("TODO implement airIntToFloat from {} to {} without sse", .{9408 16, 80, 128 => null,
9410 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),9409 else => unreachable,
9411 }),9410 },
9412 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2))9411 else => null,
9413 .{ ._, .cvtsi2sd }9412 })) |tag| tag else return self.fail("TODO implement airIntToFloat from {} to {}", .{
9414 else9413 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
9415 return self.fail("TODO implement airIntToFloat from {} to {} without sse2", .{9414 });
9416 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),9415 const dst_alias = dst_reg.to128();
9417 }),9416 const src_alias = registerAlias(src_reg, src_size);
9418 else => return self.fail("TODO implement airIntToFloat from {} to {}", .{9417 switch (mir_tag[0]) {
9419 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),9418 .v_ss, .v_sd => try self.asmRegisterRegisterRegister(mir_tag, dst_alias, dst_alias, src_alias),
9420 }),9419 else => try self.asmRegisterRegister(mir_tag, dst_alias, src_alias),
9421 }, dst_reg.to128(), registerAlias(src_reg, src_size));9420 }
94229421
9423 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });9422 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
9424}9423}
...@@ -9428,46 +9427,50 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {...@@ -9428,46 +9427,50 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
94289427
9429 const src_ty = self.air.typeOf(ty_op.operand);9428 const src_ty = self.air.typeOf(ty_op.operand);
9430 const dst_ty = self.air.typeOfIndex(inst);9429 const dst_ty = self.air.typeOfIndex(inst);
9431 const operand = try self.resolveInst(ty_op.operand);9430 const dst_bits = @intCast(u32, dst_ty.bitSize(self.target.*));
9432 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));9431 const dst_signedness =
9433 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));9432 if (dst_ty.isAbiInt()) dst_ty.intInfo(self.target.*).signedness else .unsigned;
94349433
9435 switch (src_abi_size) {9434 const dst_size = std.math.divCeil(u32, @max(switch (dst_signedness) {
9436 4, 8 => {},9435 .signed => dst_bits,
9437 else => |size| return self.fail("TODO load ST(0) with abiSize={}", .{size}),9436 .unsigned => dst_bits + 1,
9438 }9437 }, 32), 8) catch unreachable;
9439 if (dst_abi_size > 8) {9438 if (dst_size > 8) return self.fail("TODO implement airFloatToInt from {} to {}", .{
9440 return self.fail("TODO convert float with abiSize={}", .{dst_abi_size});9439 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
9441 }9440 });
94429441
9443 // move float src to ST(0)9442 const src_mcv = try self.resolveInst(ty_op.operand);
9444 const frame_addr: FrameAddr = switch (operand) {9443 const src_reg = if (src_mcv.isRegister())
9445 .load_frame => |frame_addr| frame_addr,9444 src_mcv.getReg().?
9446 else => frame_addr: {9445 else
9447 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(src_ty, self.target.*));9446 try self.copyToTmpRegister(src_ty, src_mcv);
9448 try self.genSetMem(.{ .frame = frame_index }, 0, src_ty, operand);9447 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
9449 break :frame_addr .{ .index = frame_index };9448 defer self.register_manager.unlockReg(src_lock);
9450 },
9451 };
9452 try self.asmMemory(
9453 .{ .f_, .ld },
9454 Memory.sib(Memory.PtrSize.fromSize(src_abi_size), .{
9455 .base = .{ .frame = frame_addr.index },
9456 .disp = frame_addr.off,
9457 }),
9458 );
94599449
9460 // convert9450 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty));
9461 const stack_dst = try self.allocRegOrMem(inst, false);9451 const dst_mcv = MCValue{ .register = dst_reg };
9462 try self.asmMemory(9452 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
9463 .{ .f_p, .istt },9453 defer self.register_manager.unlockReg(dst_lock);
9464 Memory.sib(Memory.PtrSize.fromSize(dst_abi_size), .{9454
9465 .base = .{ .frame = stack_dst.load_frame.index },9455 try self.asmRegisterRegister(
9466 .disp = stack_dst.load_frame.off,9456 if (@as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag()) {
9457 .Float => switch (src_ty.floatBits(self.target.*)) {
9458 32 => if (self.hasFeature(.avx)) .{ .v_, .cvttss2si } else .{ ._, .cvttss2si },
9459 64 => if (self.hasFeature(.avx)) .{ .v_, .cvttsd2si } else .{ ._, .cvttsd2si },
9460 16, 80, 128 => null,
9461 else => unreachable,
9462 },
9463 else => null,
9464 })) |tag| tag else return self.fail("TODO implement airFloatToInt from {} to {}", .{
9465 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
9467 }),9466 }),
9467 registerAlias(dst_reg, dst_size),
9468 src_reg.to128(),
9468 );9469 );
94699470
9470 return self.finishAir(inst, stack_dst, .{ ty_op.operand, .none, .none });9471 if (dst_bits < dst_size * 8) try self.truncateRegister(dst_ty, dst_reg);
9472
9473 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
9471}9474}
94729475
9473fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {9476fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
...@@ -10997,13 +11000,13 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {...@@ -10997,13 +11000,13 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
10997 reg.to64()11000 reg.to64()
10998 else11001 else
10999 unreachable,11002 unreachable,
11000 .floating_point => if (size_bytes <= 16)11003 .segment, .x87, .mmx => unreachable,
11004 .sse => if (size_bytes <= 16)
11001 reg.to128()11005 reg.to128()
11002 else if (size_bytes <= 32)11006 else if (size_bytes <= 32)
11003 reg.to256()11007 reg.to256()
11004 else11008 else
11005 unreachable,11009 unreachable,
11006 .segment => unreachable,
11007 };11010 };
11008}11011}
1100911012
src/arch/x86_64/Encoding.zig+88-71
...@@ -233,7 +233,6 @@ pub const Mnemonic = enum {...@@ -233,7 +233,6 @@ pub const Mnemonic = enum {
233 cmpxchg, cmpxchg8b, cmpxchg16b,233 cmpxchg, cmpxchg8b, cmpxchg16b,
234 cqo, cwd, cwde,234 cqo, cwd, cwde,
235 div,235 div,
236 fisttp, fld,
237 idiv, imul, int3,236 idiv, imul, int3,
238 ja, jae, jb, jbe, jc, jrcxz, je, jg, jge, jl, jle, jna, jnae, jnb, jnbe,237 ja, jae, jb, jbe, jc, jrcxz, je, jg, jge, jl, jle, jna, jnae, jnb, jnbe,
239 jnc, jne, jng, jnge, jnl, jnle, jno, jnp, jns, jnz, jo, jp, jpe, jpo, js, jz,238 jnc, jne, jng, jnge, jnl, jnle, jno, jnp, jns, jnz, jo, jp, jpe, jpo, js, jz,
...@@ -259,6 +258,8 @@ pub const Mnemonic = enum {...@@ -259,6 +258,8 @@ pub const Mnemonic = enum {
259 @"test", tzcnt,258 @"test", tzcnt,
260 ud2,259 ud2,
261 xadd, xchg, xor,260 xadd, xchg, xor,
261 // X87
262 fisttp, fld,
262 // MMX263 // MMX
263 movd,264 movd,
264 // SSE265 // SSE
...@@ -266,7 +267,7 @@ pub const Mnemonic = enum {...@@ -266,7 +267,7 @@ pub const Mnemonic = enum {
266 andps,267 andps,
267 andnps,268 andnps,
268 cmpss,269 cmpss,
269 cvtsi2ss,270 cvtpi2ps, cvtps2pi, cvtsi2ss, cvtss2si, cvttps2pi, cvttss2si,
270 divps, divss,271 divps, divss,
271 maxps, maxss,272 maxps, maxss,
272 minps, minss,273 minps, minss,
...@@ -285,7 +286,9 @@ pub const Mnemonic = enum {...@@ -285,7 +286,9 @@ pub const Mnemonic = enum {
285 andpd,286 andpd,
286 andnpd,287 andnpd,
287 //cmpsd,288 //cmpsd,
288 cvtsd2ss, cvtsi2sd, cvtss2sd,289 cvtdq2pd, cvtdq2ps, cvtpd2dq, cvtpd2pi, cvtpd2ps, cvtpi2pd,
290 cvtps2dq, cvtps2pd, cvtsd2si, cvtsd2ss, cvtsi2sd, cvtss2sd,
291 cvttpd2dq, cvttpd2pi, cvttps2dq, cvttsd2si,
289 divpd, divsd,292 divpd, divsd,
290 maxpd, maxsd,293 maxpd, maxsd,
291 minpd, minsd,294 minpd, minsd,
...@@ -314,7 +317,10 @@ pub const Mnemonic = enum {...@@ -314,7 +317,10 @@ pub const Mnemonic = enum {
314 // AVX317 // AVX
315 vaddpd, vaddps, vaddsd, vaddss,318 vaddpd, vaddps, vaddsd, vaddss,
316 vbroadcastf128, vbroadcastsd, vbroadcastss,319 vbroadcastf128, vbroadcastsd, vbroadcastss,
317 vcvtsd2ss, vcvtsi2sd, vcvtsi2ss, vcvtss2sd,320 vcvtdq2pd, vcvtdq2ps, vcvtpd2dq, vcvtpd2ps,
321 vcvtps2dq, vcvtps2pd, vcvtsd2si, vcvtsd2ss,
322 vcvtsi2sd, vcvtsi2ss, vcvtss2sd, vcvtss2si,
323 vcvttpd2dq, vcvttps2dq, vcvttsd2si, vcvttss2si,
318 vdivpd, vdivps, vdivsd, vdivss,324 vdivpd, vdivps, vdivsd, vdivss,
319 vextractf128, vextractps,325 vextractf128, vextractps,
320 vinsertf128, vinsertps,326 vinsertf128, vinsertps,
...@@ -377,80 +383,84 @@ pub const Op = enum {...@@ -377,80 +383,84 @@ pub const Op = enum {
377 m,383 m,
378 moffs,384 moffs,
379 sreg,385 sreg,
386 st, mm, mm_m64,
380 xmm, xmm_m32, xmm_m64, xmm_m128,387 xmm, xmm_m32, xmm_m64, xmm_m128,
381 ymm, ymm_m256,388 ymm, ymm_m256,
382 // zig fmt: on389 // zig fmt: on
383390
384 pub fn fromOperand(operand: Instruction.Operand) Op {391 pub fn fromOperand(operand: Instruction.Operand) Op {
385 switch (operand) {392 return switch (operand) {
386 .none => return .none,393 .none => .none,
387394
388 .reg => |reg| {395 .reg => |reg| switch (reg.class()) {
389 switch (reg.class()) {396 .general_purpose => if (reg.to64() == .rax)
390 .segment => return .sreg,397 switch (reg) {
391 .floating_point => return switch (reg.bitSize()) {398 .al => .al,
392 128 => .xmm,399 .ax => .ax,
393 256 => .ymm,400 .eax => .eax,
401 .rax => .rax,
394 else => unreachable,402 else => unreachable,
395 },403 }
396 .general_purpose => {404 else if (reg == .cl)
397 if (reg.to64() == .rax) return switch (reg) {405 .cl
398 .al => .al,406 else switch (reg.bitSize()) {
399 .ax => .ax,407 8 => .r8,
400 .eax => .eax,408 16 => .r16,
401 .rax => .rax,409 32 => .r32,
402 else => unreachable,410 64 => .r64,
403 };411 else => unreachable,
404 if (reg == .cl) return .cl;412 },
405 return switch (reg.bitSize()) {413 .segment => .sreg,
406 8 => .r8,414 .x87 => .st,
407 16 => .r16,415 .mmx => .mm,
408 32 => .r32,416 .sse => switch (reg.bitSize()) {
409 64 => .r64,417 128 => .xmm,
410 else => unreachable,418 256 => .ymm,
411 };419 else => unreachable,
412 },420 },
413 }
414 },421 },
415422
416 .mem => |mem| switch (mem) {423 .mem => |mem| switch (mem) {
417 .moffs => return .moffs,424 .moffs => .moffs,
418 .sib, .rip => {425 .sib, .rip => switch (mem.bitSize()) {
419 const bit_size = mem.bitSize();426 8 => .m8,
420 return switch (bit_size) {427 16 => .m16,
421 8 => .m8,428 32 => .m32,
422 16 => .m16,429 64 => .m64,
423 32 => .m32,430 80 => .m80,
424 64 => .m64,431 128 => .m128,
425 80 => .m80,432 256 => .m256,
426 128 => .m128,433 else => unreachable,
427 256 => .m256,
428 else => unreachable,
429 };
430 },434 },
431 },435 },
432436
433 .imm => |imm| {437 .imm => |imm| switch (imm) {
434 switch (imm) {438 .signed => |x| if (x == 1)
435 .signed => |x| {439 .unity
436 if (x == 1) return .unity;440 else if (math.cast(i8, x)) |_|
437 if (math.cast(i8, x)) |_| return .imm8s;441 .imm8s
438 if (math.cast(i16, x)) |_| return .imm16s;442 else if (math.cast(i16, x)) |_|
439 return .imm32s;443 .imm16s
440 },444 else
441 .unsigned => |x| {445 .imm32s,
442 if (x == 1) return .unity;446 .unsigned => |x| if (x == 1)
443 if (math.cast(i8, x)) |_| return .imm8s;447 .unity
444 if (math.cast(u8, x)) |_| return .imm8;448 else if (math.cast(i8, x)) |_|
445 if (math.cast(i16, x)) |_| return .imm16s;449 .imm8s
446 if (math.cast(u16, x)) |_| return .imm16;450 else if (math.cast(u8, x)) |_|
447 if (math.cast(i32, x)) |_| return .imm32s;451 .imm8
448 if (math.cast(u32, x)) |_| return .imm32;452 else if (math.cast(i16, x)) |_|
449 return .imm64;453 .imm16s
450 },454 else if (math.cast(u16, x)) |_|
451 }455 .imm16
456 else if (math.cast(i32, x)) |_|
457 .imm32s
458 else if (math.cast(u32, x)) |_|
459 .imm32
460 else
461 .imm64,
452 },462 },
453 }463 };
454 }464 }
455465
456 pub fn immBitSize(op: Op) u64 {466 pub fn immBitSize(op: Op) u64 {
...@@ -460,6 +470,7 @@ pub const Op = enum {...@@ -460,6 +470,7 @@ pub const Op = enum {
460 .ax, .r16, .rm16 => unreachable,470 .ax, .r16, .rm16 => unreachable,
461 .eax, .r32, .rm32, .r32_m16 => unreachable,471 .eax, .r32, .rm32, .r32_m16 => unreachable,
462 .rax, .r64, .rm64, .r64_m16 => unreachable,472 .rax, .r64, .rm64, .r64_m16 => unreachable,
473 .st, .mm, .mm_m64 => unreachable,
463 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => unreachable,474 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => unreachable,
464 .ymm, .ymm_m256 => unreachable,475 .ymm, .ymm_m256 => unreachable,
465 .m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable,476 .m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable,
...@@ -480,7 +491,8 @@ pub const Op = enum {...@@ -480,7 +491,8 @@ pub const Op = enum {
480 .al, .cl, .r8, .rm8 => 8,491 .al, .cl, .r8, .rm8 => 8,
481 .ax, .r16, .rm16 => 16,492 .ax, .r16, .rm16 => 16,
482 .eax, .r32, .rm32, .r32_m8, .r32_m16 => 32,493 .eax, .r32, .rm32, .r32_m8, .r32_m16 => 32,
483 .rax, .r64, .rm64, .r64_m16 => 64,494 .rax, .r64, .rm64, .r64_m16, .mm, .mm_m64 => 64,
495 .st => 80,
484 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => 128,496 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => 128,
485 .ymm, .ymm_m256 => 256,497 .ymm, .ymm_m256 => 256,
486 };498 };
...@@ -491,11 +503,11 @@ pub const Op = enum {...@@ -491,11 +503,11 @@ pub const Op = enum {
491 .none, .o16, .o32, .o64, .moffs, .m, .sreg => unreachable,503 .none, .o16, .o32, .o64, .moffs, .m, .sreg => unreachable,
492 .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable,504 .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable,
493 .rel8, .rel16, .rel32 => unreachable,505 .rel8, .rel16, .rel32 => unreachable,
494 .al, .cl, .r8, .ax, .r16, .eax, .r32, .rax, .r64, .xmm, .ymm => unreachable,506 .al, .cl, .r8, .ax, .r16, .eax, .r32, .rax, .r64, .st, .mm, .xmm, .ymm => unreachable,
495 .m8, .rm8, .r32_m8 => 8,507 .m8, .rm8, .r32_m8 => 8,
496 .m16, .rm16, .r32_m16, .r64_m16 => 16,508 .m16, .rm16, .r32_m16, .r64_m16 => 16,
497 .m32, .rm32, .xmm_m32 => 32,509 .m32, .rm32, .xmm_m32 => 32,
498 .m64, .rm64, .xmm_m64 => 64,510 .m64, .rm64, .mm_m64, .xmm_m64 => 64,
499 .m80 => 80,511 .m80 => 80,
500 .m128, .xmm_m128 => 128,512 .m128, .xmm_m128 => 128,
501 .m256, .ymm_m256 => 256,513 .m256, .ymm_m256 => 256,
...@@ -522,6 +534,7 @@ pub const Op = enum {...@@ -522,6 +534,7 @@ pub const Op = enum {
522 .r8, .r16, .r32, .r64,534 .r8, .r16, .r32, .r64,
523 .rm8, .rm16, .rm32, .rm64,535 .rm8, .rm16, .rm32, .rm64,
524 .r32_m8, .r32_m16, .r64_m16,536 .r32_m8, .r32_m16, .r64_m16,
537 .st, .mm, .mm_m64,
525 .xmm, .xmm_m32, .xmm_m64, .xmm_m128,538 .xmm, .xmm_m32, .xmm_m64, .xmm_m128,
526 .ymm, .ymm_m256,539 .ymm, .ymm_m256,
527 => true,540 => true,
...@@ -550,6 +563,7 @@ pub const Op = enum {...@@ -550,6 +563,7 @@ pub const Op = enum {
550 .r32_m8, .r32_m16, .r64_m16,563 .r32_m8, .r32_m16, .r64_m16,
551 .m8, .m16, .m32, .m64, .m80, .m128, .m256,564 .m8, .m16, .m32, .m64, .m80, .m128, .m256,
552 .m,565 .m,
566 .mm_m64,
553 .xmm_m32, .xmm_m64, .xmm_m128,567 .xmm_m32, .xmm_m64, .xmm_m128,
554 .ymm_m256,568 .ymm_m256,
555 => true,569 => true,
...@@ -573,8 +587,10 @@ pub const Op = enum {...@@ -573,8 +587,10 @@ pub const Op = enum {
573 .rm8, .rm16, .rm32, .rm64 => .general_purpose,587 .rm8, .rm16, .rm32, .rm64 => .general_purpose,
574 .r32_m8, .r32_m16, .r64_m16 => .general_purpose,588 .r32_m8, .r32_m16, .r64_m16 => .general_purpose,
575 .sreg => .segment,589 .sreg => .segment,
576 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => .floating_point,590 .st => .x87,
577 .ymm, .ymm_m256 => .floating_point,591 .mm, .mm_m64 => .mmx,
592 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => .sse,
593 .ymm, .ymm_m256 => .sse,
578 };594 };
579 }595 }
580596
...@@ -695,6 +711,7 @@ pub const Feature = enum {...@@ -695,6 +711,7 @@ pub const Feature = enum {
695 f16c,711 f16c,
696 fma,712 fma,
697 lzcnt,713 lzcnt,
714 movbe,
698 popcnt,715 popcnt,
699 sse,716 sse,
700 sse2,717 sse2,
...@@ -717,7 +734,7 @@ fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Op...@@ -717,7 +734,7 @@ fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Op
717}734}
718735
719const mnemonic_to_encodings_map = init: {736const mnemonic_to_encodings_map = init: {
720 @setEvalBranchQuota(20_000);737 @setEvalBranchQuota(25_000);
721 const encodings = @import("encodings.zig");738 const encodings = @import("encodings.zig");
722 var entries = encodings.table;739 var entries = encodings.table;
723 std.sort.sort(encodings.Entry, &entries, {}, struct {740 std.sort.sort(encodings.Entry, &entries, {}, struct {
src/arch/x86_64/Mir.zig+40-6
...@@ -439,8 +439,21 @@ pub const Inst = struct {...@@ -439,8 +439,21 @@ pub const Inst = struct {
439 /// Bitwise logical and not of packed single-precision floating-point values439 /// Bitwise logical and not of packed single-precision floating-point values
440 /// Bitwise logical and not of packed double-precision floating-point values440 /// Bitwise logical and not of packed double-precision floating-point values
441 andn,441 andn,
442 /// Convert packed doubleword integers to packed single-precision floating-point values
443 /// Convert packed doubleword integers to packed double-precision floating-point values
444 cvtpi2,
445 /// Convert packed single-precision floating-point values to packed doubleword integers
446 cvtps2pi,
442 /// Convert doubleword integer to scalar single-precision floating-point value447 /// Convert doubleword integer to scalar single-precision floating-point value
443 cvtsi2ss,448 /// Convert doubleword integer to scalar double-precision floating-point value
449 cvtsi2,
450 /// Convert scalar single-precision floating-point value to doubleword integer
451 cvtss2si,
452 /// Convert with truncation packed single-precision floating-point values to packed doubleword integers
453 cvttps2pi,
454 /// Convert with truncation scalar single-precision floating-point value to doubleword integer
455 cvttss2si,
456
444 /// Maximum of packed single-precision floating-point values457 /// Maximum of packed single-precision floating-point values
445 /// Maximum of scalar single-precision floating-point values458 /// Maximum of scalar single-precision floating-point values
446 /// Maximum of packed double-precision floating-point values459 /// Maximum of packed double-precision floating-point values
...@@ -486,12 +499,33 @@ pub const Inst = struct {...@@ -486,12 +499,33 @@ pub const Inst = struct {
486 /// Unpack and interleave low packed double-precision floating-point values499 /// Unpack and interleave low packed double-precision floating-point values
487 unpckl,500 unpckl,
488501
502 /// Convert packed doubleword integers to packed single-precision floating-point values
503 /// Convert packed doubleword integers to packed double-precision floating-point values
504 cvtdq2,
505 /// Convert packed double-precision floating-point values to packed doubleword integers
506 cvtpd2dq,
507 /// Convert packed double-precision floating-point values to packed doubleword integers
508 cvtpd2pi,
509 /// Convert packed double-precision floating-point values to packed single-precision floating-point values
510 cvtpd2,
511 /// Convert packed single-precision floating-point values to packed doubleword integers
512 cvtps2dq,
513 /// Convert packed single-precision floating-point values to packed double-precision floating-point values
514 cvtps2,
515 /// Convert scalar double-precision floating-point value to doubleword integer
516 cvtsd2si,
489 /// Convert scalar double-precision floating-point value to scalar single-precision floating-point value517 /// Convert scalar double-precision floating-point value to scalar single-precision floating-point value
490 cvtsd2ss,518 cvtsd2,
491 /// Convert doubleword integer to scalar double-precision floating-point value
492 cvtsi2sd,
493 /// Convert scalar single-precision floating-point value to scalar double-precision floating-point value519 /// Convert scalar single-precision floating-point value to scalar double-precision floating-point value
494 cvtss2sd,520 cvtss2,
521 /// Convert with truncation packed double-precision floating-point values to packed doubleword integers
522 cvttpd2dq,
523 /// Convert with truncation packed double-precision floating-point values to packed doubleword integers
524 cvttpd2pi,
525 /// Convert with truncation packed single-precision floating-point values to packed doubleword integers
526 cvttps2dq,
527 /// Convert with truncation scalar double-precision floating-point value to doubleword integer
528 cvttsd2si,
495 /// Packed interleave shuffle of quadruplets of single-precision floating-point values529 /// Packed interleave shuffle of quadruplets of single-precision floating-point values
496 /// Packed interleave shuffle of pairs of double-precision floating-point values530 /// Packed interleave shuffle of pairs of double-precision floating-point values
497 shuf,531 shuf,
...@@ -542,7 +576,7 @@ pub const Inst = struct {...@@ -542,7 +576,7 @@ pub const Inst = struct {
542 broadcast,576 broadcast,
543577
544 /// Convert 16-bit floating-point values to single-precision floating-point values578 /// Convert 16-bit floating-point values to single-precision floating-point values
545 cvtph2ps,579 cvtph2,
546 /// Convert single-precision floating-point values to 16-bit floating-point values580 /// Convert single-precision floating-point values to 16-bit floating-point values
547 cvtps2ph,581 cvtps2ph,
548582
src/arch/x86_64/bits.zig+38-45
...@@ -175,15 +175,21 @@ pub const Register = enum(u7) {...@@ -175,15 +175,21 @@ pub const Register = enum(u7) {
175 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,175 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
176 xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,176 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
178 es, cs, ss, ds, fs, gs,182 es, cs, ss, ds, fs, gs,
179183
180 none,184 none,
181 // zig fmt: on185 // zig fmt: on
182186
183 pub const Class = enum(u2) {187 pub const Class = enum {
184 general_purpose,188 general_purpose,
185 floating_point,
186 segment,189 segment,
190 x87,
191 mmx,
192 sse,
187 };193 };
188194
189 pub fn class(reg: Register) Class {195 pub fn class(reg: Register) Class {
...@@ -195,8 +201,10 @@ pub const Register = enum(u7) {...@@ -195,8 +201,10 @@ pub const Register = enum(u7) {
195 @enumToInt(Register.al) ... @enumToInt(Register.r15b) => .general_purpose,201 @enumToInt(Register.al) ... @enumToInt(Register.r15b) => .general_purpose,
196 @enumToInt(Register.ah) ... @enumToInt(Register.bh) => .general_purpose,202 @enumToInt(Register.ah) ... @enumToInt(Register.bh) => .general_purpose,
197203
198 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => .floating_point,204 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => .sse,
199 @enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => .floating_point,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
201 @enumToInt(Register.es) ... @enumToInt(Register.gs) => .segment,209 @enumToInt(Register.es) ... @enumToInt(Register.gs) => .segment,
202210
...@@ -216,8 +224,10 @@ pub const Register = enum(u7) {...@@ -216,8 +224,10 @@ pub const Register = enum(u7) {
216224
217 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => @enumToInt(Register.ymm0) - 16,225 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => @enumToInt(Register.ymm0) - 16,
218 @enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => @enumToInt(Register.xmm0) - 16,226 @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
222 else => unreachable,232 else => unreachable,
223 // zig fmt: on233 // zig fmt: on
...@@ -236,6 +246,8 @@ pub const Register = enum(u7) {...@@ -236,6 +246,8 @@ pub const Register = enum(u7) {
236246
237 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => 256,247 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => 256,
238 @enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => 128,248 @enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => 128,
249 @enumToInt(Register.mm0) ... @enumToInt(Register.mm7) => 64,
250 @enumToInt(Register.st0) ... @enumToInt(Register.st7) => 80,
239251
240 @enumToInt(Register.es) ... @enumToInt(Register.gs) => 16,252 @enumToInt(Register.es) ... @enumToInt(Register.gs) => 16,
241253
...@@ -271,6 +283,8 @@ pub const Register = enum(u7) {...@@ -271,6 +283,8 @@ pub const Register = enum(u7) {
271283
272 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => @enumToInt(Register.ymm0),284 @enumToInt(Register.ymm0) ... @enumToInt(Register.ymm15) => @enumToInt(Register.ymm0),
273 @enumToInt(Register.xmm0) ... @enumToInt(Register.xmm15) => @enumToInt(Register.xmm0),285 @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
275 @enumToInt(Register.es) ... @enumToInt(Register.gs) => @enumToInt(Register.es),289 @enumToInt(Register.es) ... @enumToInt(Register.gs) => @enumToInt(Register.es),
276290
...@@ -326,8 +340,8 @@ pub const Register = enum(u7) {...@@ -326,8 +340,8 @@ pub const Register = enum(u7) {
326 return @intToEnum(Register, @enumToInt(reg) - reg.gpBase() + @enumToInt(Register.al));340 return @intToEnum(Register, @enumToInt(reg) - reg.gpBase() + @enumToInt(Register.al));
327 }341 }
328342
329 fn fpBase(reg: Register) u7 {343 fn sseBase(reg: Register) u7 {
330 assert(reg.class() == .floating_point);344 assert(reg.class() == .sse);
331 return switch (@enumToInt(reg)) {345 return switch (@enumToInt(reg)) {
332 @enumToInt(Register.ymm0)...@enumToInt(Register.ymm15) => @enumToInt(Register.ymm0),346 @enumToInt(Register.ymm0)...@enumToInt(Register.ymm15) => @enumToInt(Register.ymm0),
333 @enumToInt(Register.xmm0)...@enumToInt(Register.xmm15) => @enumToInt(Register.xmm0),347 @enumToInt(Register.xmm0)...@enumToInt(Register.xmm15) => @enumToInt(Register.xmm0),
...@@ -336,49 +350,24 @@ pub const Register = enum(u7) {...@@ -336,49 +350,24 @@ pub const Register = enum(u7) {
336 }350 }
337351
338 pub fn to256(reg: Register) Register {352 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));
340 }354 }
341355
342 pub fn to128(reg: Register) Register {356 pub fn to128(reg: Register) Register {
343 return @intToEnum(Register, @enumToInt(reg) - reg.fpBase() + @enumToInt(Register.xmm0));357 return @intToEnum(Register, @enumToInt(reg) - reg.sseBase() + @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 };
362 }358 }
363359
364 /// DWARF encodings that push a value onto the DWARF stack that is either360 /// DWARF register encoding
365 /// the contents of a register or the result of adding the contents a given361 pub fn dwarfNum(reg: Register) u6 {
366 /// register to a given signed offset.
367 pub fn dwarfLocOpDeref(reg: Register) u8 {
368 return switch (reg.class()) {362 return switch (reg.class()) {
369 .general_purpose => switch (reg.to64()) {363 .general_purpose => if (reg.isExtended())
370 .rax => DW.OP.breg0,364 reg.enc()
371 .rdx => DW.OP.breg1,365 else
372 .rcx => DW.OP.breg2,366 @truncate(u3, @as(u24, 0o54673120) >> @as(u5, reg.enc()) * 3),
373 .rbx => DW.OP.breg3,367 .sse => 17 + @as(u6, reg.enc()),
374 .rsi => DW.OP.breg4,368 .x87 => 33 + @as(u6, reg.enc()),
375 .rdi => DW.OP.breg5,369 .mmx => 41 + @as(u6, reg.enc()),
376 .rbp => DW.OP.breg6,370 .segment => 50 + @as(u6, reg.enc()),
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,
382 };371 };
383 }372 }
384};373};
...@@ -392,6 +381,8 @@ test "Register id - different classes" {...@@ -392,6 +381,8 @@ test "Register id - different classes" {
392 try expect(Register.ymm0.id() == 0b10000);381 try expect(Register.ymm0.id() == 0b10000);
393 try expect(Register.ymm0.id() != Register.rax.id());382 try expect(Register.ymm0.id() != Register.rax.id());
394 try expect(Register.xmm0.id() == Register.ymm0.id());383 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
396 try expect(Register.es.id() == 0b100000);387 try expect(Register.es.id() == 0b100000);
397}388}
...@@ -407,7 +398,9 @@ test "Register enc - different classes" {...@@ -407,7 +398,9 @@ test "Register enc - different classes" {
407398
408test "Register classes" {399test "Register classes" {
409 try expect(Register.r11.class() == .general_purpose);400 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);
411 try expect(Register.fs.class() == .segment);404 try expect(Register.fs.class() == .segment);
412}405}
413406
src/arch/x86_64/encodings.zig+94-17
...@@ -272,14 +272,6 @@ pub const table = [_]Entry{...@@ -272,14 +272,6 @@ pub const table = [_]Entry{
272 .{ .div, .m, &.{ .rm32 }, &.{ 0xf7 }, 6, .none, .none },272 .{ .div, .m, &.{ .rm32 }, &.{ 0xf7 }, 6, .none, .none },
273 .{ .div, .m, &.{ .rm64 }, &.{ 0xf7 }, 6, .long, .none },273 .{ .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
283 .{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .none, .none },275 .{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .none, .none },
284 .{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .rex, .none },276 .{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .rex, .none },
285 .{ .idiv, .m, &.{ .rm16 }, &.{ 0xf7 }, 7, .short, .none },277 .{ .idiv, .m, &.{ .rm16 }, &.{ 0xf7 }, 7, .short, .none },
...@@ -395,12 +387,12 @@ pub const table = [_]Entry{...@@ -395,12 +387,12 @@ pub const table = [_]Entry{
395 .{ .mov, .mi, &.{ .rm32, .imm32 }, &.{ 0xc7 }, 0, .none, .none },387 .{ .mov, .mi, &.{ .rm32, .imm32 }, &.{ 0xc7 }, 0, .none, .none },
396 .{ .mov, .mi, &.{ .rm64, .imm32s }, &.{ 0xc7 }, 0, .long, .none },388 .{ .mov, .mi, &.{ .rm64, .imm32s }, &.{ 0xc7 }, 0, .long, .none },
397389
398 .{ .movbe, .rm, &.{ .r16, .m16 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .short, .none },390 .{ .movbe, .rm, &.{ .r16, .m16 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .short, .movbe },
399 .{ .movbe, .rm, &.{ .r32, .m32 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .none, .none },391 .{ .movbe, .rm, &.{ .r32, .m32 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .none, .movbe },
400 .{ .movbe, .rm, &.{ .r64, .m64 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .long, .none },392 .{ .movbe, .rm, &.{ .r64, .m64 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .long, .movbe },
401 .{ .movbe, .mr, &.{ .m16, .r16 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .short, .none },393 .{ .movbe, .mr, &.{ .m16, .r16 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .short, .movbe },
402 .{ .movbe, .mr, &.{ .m32, .r32 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none, .none },394 .{ .movbe, .mr, &.{ .m32, .r32 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none, .movbe },
403 .{ .movbe, .mr, &.{ .m64, .r64 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .long, .none },395 .{ .movbe, .mr, &.{ .m64, .r64 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .long, .movbe },
404396
405 .{ .movs, .np, &.{ .m8, .m8 }, &.{ 0xa4 }, 0, .none, .none },397 .{ .movs, .np, &.{ .m8, .m8 }, &.{ 0xa4 }, 0, .none, .none },
406 .{ .movs, .np, &.{ .m16, .m16 }, &.{ 0xa5 }, 0, .short, .none },398 .{ .movs, .np, &.{ .m16, .m16 }, &.{ 0xa5 }, 0, .short, .none },
...@@ -836,6 +828,15 @@ pub const table = [_]Entry{...@@ -836,6 +828,15 @@ pub const table = [_]Entry{
836 .{ .xor, .rm, &.{ .r32, .rm32 }, &.{ 0x33 }, 0, .none, .none },828 .{ .xor, .rm, &.{ .r32, .rm32 }, &.{ 0x33 }, 0, .none, .none },
837 .{ .xor, .rm, &.{ .r64, .rm64 }, &.{ 0x33 }, 0, .long, .none },829 .{ .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
839 // SSE840 // SSE
840 .{ .addps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x58 }, 0, .none, .sse },841 .{ .addps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x58 }, 0, .none, .sse },
841842
...@@ -847,9 +848,21 @@ pub const table = [_]Entry{...@@ -847,9 +848,21 @@ pub const table = [_]Entry{
847848
848 .{ .cmpss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0xf3, 0x0f, 0xc2 }, 0, .none, .sse },849 .{ .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
850 .{ .cvtsi2ss, .rm, &.{ .xmm, .rm32 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .none, .sse },855 .{ .cvtsi2ss, .rm, &.{ .xmm, .rm32 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .none, .sse },
851 .{ .cvtsi2ss, .rm, &.{ .xmm, .rm64 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .long, .sse },856 .{ .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
853 .{ .divps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5e }, 0, .none, .sse },866 .{ .divps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5e }, 0, .none, .sse },
854867
855 .{ .divss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5e }, 0, .none, .sse },868 .{ .divss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5e }, 0, .none, .sse },
...@@ -906,6 +919,25 @@ pub const table = [_]Entry{...@@ -906,6 +919,25 @@ pub const table = [_]Entry{
906919
907 .{ .cmpsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0xf2, 0x0f, 0xc2 }, 0, .none, .sse2 },920 .{ .cmpsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0xf2, 0x0f, 0xc2 }, 0, .none, .sse2 },
908921
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
909 .{ .cvtsd2ss, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .none, .sse2 },941 .{ .cvtsd2ss, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .none, .sse2 },
910942
911 .{ .cvtsi2sd, .rm, &.{ .xmm, .rm32 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .none, .sse2 },943 .{ .cvtsi2sd, .rm, &.{ .xmm, .rm32 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .none, .sse2 },
...@@ -913,6 +945,15 @@ pub const table = [_]Entry{...@@ -913,6 +945,15 @@ pub const table = [_]Entry{
913945
914 .{ .cvtss2sd, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5a }, 0, .none, .sse2 },946 .{ .cvtss2sd, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5a }, 0, .none, .sse2 },
915947
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
916 .{ .divpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5e }, 0, .none, .sse2 },957 .{ .divpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5e }, 0, .none, .sse2 },
917958
918 .{ .divsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5e }, 0, .none, .sse2 },959 .{ .divsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5e }, 0, .none, .sse2 },
...@@ -1034,15 +1075,51 @@ pub const table = [_]Entry{...@@ -1034,15 +1075,51 @@ pub const table = [_]Entry{
1034 .{ .vbroadcastsd, .rm, &.{ .ymm, .m64 }, &.{ 0x66, 0x0f, 0x38, 0x19 }, 0, .vex_256_w0, .avx },1075 .{ .vbroadcastsd, .rm, &.{ .ymm, .m64 }, &.{ 0x66, 0x0f, 0x38, 0x19 }, 0, .vex_256_w0, .avx },
1035 .{ .vbroadcastf128, .rm, &.{ .ymm, .m128 }, &.{ 0x66, 0x0f, 0x38, 0x1a }, 0, .vex_256_w0, .avx },1076 .{ .vbroadcastf128, .rm, &.{ .ymm, .m128 }, &.{ 0x66, 0x0f, 0x38, 0x1a }, 0, .vex_256_w0, .avx },
10361077
1078 .{ .vcvtdq2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0xe6 }, 0, .vex_128_wig, .avx },
1079 .{ .vcvtdq2pd, .rm, &.{ .ymm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0xe6 }, 0, .vex_256_wig, .avx },
1080
1081 .{ .vcvtdq2ps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5b }, 0, .vex_128_wig, .avx },
1082 .{ .vcvtdq2ps, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x0f, 0x5b }, 0, .vex_256_wig, .avx },
1083
1084 .{ .vcvtpd2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf2, 0x0f, 0xe6 }, 0, .vex_128_wig, .avx },
1085 .{ .vcvtpd2dq, .rm, &.{ .xmm, .ymm_m256 }, &.{ 0xf2, 0x0f, 0xe6 }, 0, .vex_256_wig, .avx },
1086
1087 .{ .vcvtpd2ps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5a }, 0, .vex_128_wig, .avx },
1088 .{ .vcvtpd2ps, .rm, &.{ .xmm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5a }, 0, .vex_256_wig, .avx },
1089
1090 .{ .vcvtps2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5b }, 0, .vex_128_wig, .avx },
1091 .{ .vcvtps2dq, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5b }, 0, .vex_256_wig, .avx },
1092
1093 .{ .vcvtps2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x0f, 0x5a }, 0, .vex_128_wig, .avx },
1094 .{ .vcvtps2pd, .rm, &.{ .ymm, .xmm_m128 }, &.{ 0x0f, 0x5a }, 0, .vex_256_wig, .avx },
1095
1096 .{ .vcvtsd2si, .rm, &.{ .r32, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2d }, 0, .vex_lig_w0, .sse2 },
1097 .{ .vcvtsd2si, .rm, &.{ .r64, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2d }, 0, .vex_lig_w1, .sse2 },
1098
1037 .{ .vcvtsd2ss, .rvm, &.{ .xmm, .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .vex_lig_wig, .avx },1099 .{ .vcvtsd2ss, .rvm, &.{ .xmm, .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .vex_lig_wig, .avx },
10381100
1039 .{ .vcvtsi2sd, .rvm, &.{ .xmm, .xmm, .rm32 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w0, .avx },1101 .{ .vcvtsi2sd, .rvm, &.{ .xmm, .xmm, .rm32 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w0, .avx },
1040 .{ .vcvtsi2sd, .rvm, &.{ .xmm, .xmm, .rm64 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w1, .avx },1102 .{ .vcvtsi2sd, .rvm, &.{ .xmm, .xmm, .rm64 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w1, .avx },
10411103
1042 .{ .vcvtsi2ss, .rvm, &.{ .xmm, .xmm, .rm32 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w0, .avx },1104 .{ .vcvtsi2ss, .rvm, &.{ .xmm, .xmm, .rm32 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .vex_lig_w0, .avx },
1043 .{ .vcvtsi2ss, .rvm, &.{ .xmm, .xmm, .rm64 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w1, .avx },1105 .{ .vcvtsi2ss, .rvm, &.{ .xmm, .xmm, .rm64 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .vex_lig_w1, .avx },
1106
1107 .{ .vcvtss2sd, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5a }, 0, .vex_lig_wig, .avx },
1108
1109 .{ .vcvtss2si, .rm, &.{ .r32, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2d }, 0, .vex_lig_w0, .avx },
1110 .{ .vcvtss2si, .rm, &.{ .r64, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2d }, 0, .vex_lig_w1, .avx },
1111
1112 .{ .vcvttpd2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xe6 }, 0, .vex_128_wig, .avx },
1113 .{ .vcvttpd2dq, .rm, &.{ .xmm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xe6 }, 0, .vex_256_wig, .avx },
1114
1115 .{ .vcvttps2dq, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0x5b }, 0, .vex_128_wig, .avx },
1116 .{ .vcvttps2dq, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0xf3, 0x0f, 0x5b }, 0, .vex_256_wig, .avx },
1117
1118 .{ .vcvttsd2si, .rm, &.{ .r32, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2c }, 0, .vex_lig_w0, .sse2 },
1119 .{ .vcvttsd2si, .rm, &.{ .r64, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x2c }, 0, .vex_lig_w1, .sse2 },
10441120
1045 .{ .vcvtss2sd, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .vex_lig_wig, .avx },1121 .{ .vcvttss2si, .rm, &.{ .r32, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2c }, 0, .vex_lig_w0, .avx },
1122 .{ .vcvttss2si, .rm, &.{ .r64, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x2c }, 0, .vex_lig_w1, .avx },
10461123
1047 .{ .vdivpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5e }, 0, .vex_128_wig, .avx },1124 .{ .vdivpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5e }, 0, .vex_128_wig, .avx },
1048 .{ .vdivpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5e }, 0, .vex_256_wig, .avx },1125 .{ .vdivpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5e }, 0, .vex_256_wig, .avx },
src/link/Dwarf.zig+68-24
...@@ -608,23 +608,44 @@ pub const DeclState = struct {...@@ -608,23 +608,44 @@ pub const DeclState = struct {
608608
609 switch (loc) {609 switch (loc) {
610 .register => |reg| {610 .register => |reg| {
611 try dbg_info.ensureUnusedCapacity(3);611 try dbg_info.ensureUnusedCapacity(4);
612 dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));612 dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));
613 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc613 // DW.AT.location, DW.FORM.exprloc
614 1, // ULEB128 dwarf expression length614 var expr_len = std.io.countingWriter(std.io.null_writer);
615 reg,615 if (reg < 32) {
616 });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 }
617 },628 },
618 .stack => |info| {629 .stack => |info| {
619 try dbg_info.ensureUnusedCapacity(8);630 try dbg_info.ensureUnusedCapacity(9);
620 dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));631 dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));
621 const fixup = dbg_info.items.len;632 // DW.AT.location, DW.FORM.exprloc
622 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc633 var expr_len = std.io.countingWriter(std.io.null_writer);
623 1, // we will backpatch it after we encode the displacement in LEB128634 if (info.fp_register < 32) {
624 info.fp_register, // frame pointer635 expr_len.writer().writeByte(DW.OP.breg0 + info.fp_register) catch unreachable;
625 });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 }
626 leb128.writeILEB128(dbg_info.writer(), info.offset) catch unreachable;648 leb128.writeILEB128(dbg_info.writer(), info.offset) catch unreachable;
627 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
628 },649 },
629 .wasm_local => |value| {650 .wasm_local => |value| {
630 const leb_size = link.File.Wasm.getULEB128Size(value);651 const leb_size = link.File.Wasm.getULEB128Size(value);
...@@ -670,22 +691,45 @@ pub const DeclState = struct {...@@ -670,22 +691,45 @@ pub const DeclState = struct {
670691
671 switch (loc) {692 switch (loc) {
672 .register => |reg| {693 .register => |reg| {
673 try dbg_info.ensureUnusedCapacity(2);694 try dbg_info.ensureUnusedCapacity(4);
674 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc695 dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));
675 1, // ULEB128 dwarf expression length696 // DW.AT.location, DW.FORM.exprloc
676 reg,697 var expr_len = std.io.countingWriter(std.io.null_writer);
677 });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 }
678 },711 },
679712
680 .stack => |info| {713 .stack => |info| {
681 try dbg_info.ensureUnusedCapacity(7);714 try dbg_info.ensureUnusedCapacity(9);
682 const fixup = dbg_info.items.len;715 dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter));
683 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc716 // DW.AT.location, DW.FORM.exprloc
684 1, // we will backpatch it after we encode the displacement in LEB128717 var expr_len = std.io.countingWriter(std.io.null_writer);
685 info.fp_register,718 if (info.fp_register < 32) {
686 });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 }
687 leb128.writeILEB128(dbg_info.writer(), info.offset) catch unreachable;732 leb128.writeILEB128(dbg_info.writer(), info.offset) catch unreachable;
688 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
689 },733 },
690734
691 .wasm_local => |value| {735 .wasm_local => |value| {
test/behavior/cast.zig-1
...@@ -153,7 +153,6 @@ test "@intToFloat(f80)" {...@@ -153,7 +153,6 @@ test "@intToFloat(f80)" {
153test "@floatToInt" {153test "@floatToInt" {
154 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO154 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
155 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO155 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
156 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
157 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO156 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO157 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
159 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;158 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;