authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-03 04:21:40-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-03 04:25:14-04:00
loga19faa2481e84e065a8762cb7c7cbf35426929fd
treebac1c8e73a43ab9a855107776ff3223528426b84
parent6893f90887836584f9377793cca7235d8947a326

x86_64: implement movement of more types

* f16 * f128 * vector

6 files changed, 198 insertions(+), 80 deletions(-)

src/arch/x86_64/CodeGen.zig+148-73
...@@ -1210,6 +1210,28 @@ fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !...@@ -1210,6 +1210,28 @@ fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !
1210 });1210 });
1211}1211}
12121212
1213fn asmRegisterMemoryImmediate(
1214 self: *Self,
1215 tag: Mir.Inst.Tag,
1216 reg: Register,
1217 m: Memory,
1218 imm: Immediate,
1219) !void {
1220 _ = try self.addInst(.{
1221 .tag = tag,
1222 .ops = switch (m) {
1223 .sib => .rmi_sib,
1224 .rip => .rmi_rip,
1225 else => unreachable,
1226 },
1227 .data = .{ .rix = .{ .r = reg, .i = @intCast(u8, imm.unsigned), .payload = switch (m) {
1228 .sib => try self.addExtra(Mir.MemorySib.encode(m)),
1229 .rip => try self.addExtra(Mir.MemoryRip.encode(m)),
1230 else => unreachable,
1231 } } },
1232 });
1233}
1234
1213fn asmMemoryRegister(self: *Self, tag: Mir.Inst.Tag, m: Memory, reg: Register) !void {1235fn asmMemoryRegister(self: *Self, tag: Mir.Inst.Tag, m: Memory, reg: Register) !void {
1214 _ = try self.addInst(.{1236 _ = try self.addInst(.{
1215 .tag = tag,1237 .tag = tag,
...@@ -1951,7 +1973,7 @@ fn allocRegOrMemAdvanced(self: *Self, elem_ty: Type, inst: ?Air.Inst.Index, reg_...@@ -1951,7 +1973,7 @@ fn allocRegOrMemAdvanced(self: *Self, elem_ty: Type, inst: ?Air.Inst.Index, reg_
1951 const ptr_bits = self.target.cpu.arch.ptrBitWidth();1973 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1952 const ptr_bytes: u64 = @divExact(ptr_bits, 8);1974 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
1953 if (abi_size <= ptr_bytes) {1975 if (abi_size <= ptr_bytes) {
1954 if (self.register_manager.tryAllocReg(inst, try self.regClassForType(elem_ty))) |reg| {1976 if (self.register_manager.tryAllocReg(inst, regClassForType(elem_ty))) |reg| {
1955 return MCValue{ .register = registerAlias(reg, abi_size) };1977 return MCValue{ .register = registerAlias(reg, abi_size) };
1956 }1978 }
1957 }1979 }
...@@ -1961,14 +1983,9 @@ fn allocRegOrMemAdvanced(self: *Self, elem_ty: Type, inst: ?Air.Inst.Index, reg_...@@ -1961,14 +1983,9 @@ fn allocRegOrMemAdvanced(self: *Self, elem_ty: Type, inst: ?Air.Inst.Index, reg_
1961 return .{ .load_frame = .{ .index = frame_index } };1983 return .{ .load_frame = .{ .index = frame_index } };
1962}1984}
19631985
1964fn regClassForType(self: *Self, ty: Type) !RegisterManager.RegisterBitSet {1986fn regClassForType(ty: Type) RegisterManager.RegisterBitSet {
1965 return switch (ty.zigTypeTag()) {1987 return switch (ty.zigTypeTag()) {
1966 .Vector => self.fail("TODO regClassForType for {}", .{ty.fmt(self.bin_file.options.module.?)}),1988 .Float, .Vector => sse,
1967 .Float => switch (ty.floatBits(self.target.*)) {
1968 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse)) sse else gp,
1969 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2)) sse else gp,
1970 else => gp,
1971 },
1972 else => gp,1989 else => gp,
1973 };1990 };
1974}1991}
...@@ -2111,7 +2128,7 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void {...@@ -2111,7 +2128,7 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void {
2111/// allocated. A second call to `copyToTmpRegister` may return the same register.2128/// allocated. A second call to `copyToTmpRegister` may return the same register.
2112/// This can have a side effect of spilling instructions to the stack to free up a register.2129/// This can have a side effect of spilling instructions to the stack to free up a register.
2113fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {2130fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
2114 const reg = try self.register_manager.allocReg(null, try self.regClassForType(ty));2131 const reg = try self.register_manager.allocReg(null, regClassForType(ty));
2115 try self.genSetReg(reg, ty, mcv);2132 try self.genSetReg(reg, ty, mcv);
2116 return reg;2133 return reg;
2117}2134}
...@@ -2126,7 +2143,7 @@ fn copyToRegisterWithInstTracking(...@@ -2126,7 +2143,7 @@ fn copyToRegisterWithInstTracking(
2126 ty: Type,2143 ty: Type,
2127 mcv: MCValue,2144 mcv: MCValue,
2128) !MCValue {2145) !MCValue {
2129 const reg: Register = try self.register_manager.allocReg(reg_owner, try self.regClassForType(ty));2146 const reg: Register = try self.register_manager.allocReg(reg_owner, regClassForType(ty));
2130 try self.genSetReg(reg, ty, mcv);2147 try self.genSetReg(reg, ty, mcv);
2131 return MCValue{ .register = reg };2148 return MCValue{ .register = reg };
2132}2149}
...@@ -2159,8 +2176,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -2159,8 +2176,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
2159 if (dst_ty.floatBits(self.target.*) != 32 or src_ty.floatBits(self.target.*) != 64 or2176 if (dst_ty.floatBits(self.target.*) != 32 or src_ty.floatBits(self.target.*) != 64 or
2160 !Target.x86.featureSetHas(self.target.cpu.features, .sse2))2177 !Target.x86.featureSetHas(self.target.cpu.features, .sse2))
2161 return self.fail("TODO implement airFptrunc from {} to {}", .{2178 return self.fail("TODO implement airFptrunc from {} to {}", .{
2162 src_ty.fmt(self.bin_file.options.module.?),2179 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
2163 dst_ty.fmt(self.bin_file.options.module.?),
2164 });2180 });
21652181
2166 const src_mcv = try self.resolveInst(ty_op.operand);2182 const src_mcv = try self.resolveInst(ty_op.operand);
...@@ -2182,8 +2198,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {...@@ -2182,8 +2198,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
2182 if (dst_ty.floatBits(self.target.*) != 64 or src_ty.floatBits(self.target.*) != 32 or2198 if (dst_ty.floatBits(self.target.*) != 64 or src_ty.floatBits(self.target.*) != 32 or
2183 !Target.x86.featureSetHas(self.target.cpu.features, .sse2))2199 !Target.x86.featureSetHas(self.target.cpu.features, .sse2))
2184 return self.fail("TODO implement airFpext from {} to {}", .{2200 return self.fail("TODO implement airFpext from {} to {}", .{
2185 src_ty.fmt(self.bin_file.options.module.?),2201 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
2186 dst_ty.fmt(self.bin_file.options.module.?),
2187 });2202 });
21882203
2189 const src_mcv = try self.resolveInst(ty_op.operand);2204 const src_mcv = try self.resolveInst(ty_op.operand);
...@@ -4436,8 +4451,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -4436,8 +4451,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
4436 const ptr_ty = self.air.typeOf(ty_op.operand);4451 const ptr_ty = self.air.typeOf(ty_op.operand);
4437 const elem_size = elem_ty.abiSize(self.target.*);4452 const elem_size = elem_ty.abiSize(self.target.*);
44384453
4439 const elem_rc = try self.regClassForType(elem_ty);4454 const elem_rc = regClassForType(elem_ty);
4440 const ptr_rc = try self.regClassForType(ptr_ty);4455 const ptr_rc = regClassForType(ptr_ty);
44414456
4442 const ptr_mcv = try self.resolveInst(ty_op.operand);4457 const ptr_mcv = try self.resolveInst(ty_op.operand);
4443 const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and4458 const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and
...@@ -5257,8 +5272,7 @@ fn genMulDivBinOp(...@@ -5257,8 +5272,7 @@ fn genMulDivBinOp(
5257 .mul, .mulwrap => dst_abi_size != src_abi_size and dst_abi_size != src_abi_size * 2,5272 .mul, .mulwrap => dst_abi_size != src_abi_size and dst_abi_size != src_abi_size * 2,
5258 .div_trunc, .div_floor, .div_exact, .rem, .mod => dst_abi_size != src_abi_size,5273 .div_trunc, .div_floor, .div_exact, .rem, .mod => dst_abi_size != src_abi_size,
5259 } or src_abi_size > 8) return self.fail("TODO implement genMulDivBinOp from {} to {}", .{5274 } or src_abi_size > 8) return self.fail("TODO implement genMulDivBinOp from {} to {}", .{
5260 src_ty.fmt(self.bin_file.options.module.?),5275 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
5261 dst_ty.fmt(self.bin_file.options.module.?),
5262 });5276 });
5263 const ty = if (dst_abi_size <= 8) dst_ty else src_ty;5277 const ty = if (dst_abi_size <= 8) dst_ty else src_ty;
5264 const abi_size = if (dst_abi_size <= 8) dst_abi_size else src_abi_size;5278 const abi_size = if (dst_abi_size <= 8) dst_abi_size else src_abi_size;
...@@ -5558,7 +5572,9 @@ fn genBinOp(...@@ -5558,7 +5572,9 @@ fn genBinOp(
5558 }, lhs_ty, dst_mcv, src_mcv),5572 }, lhs_ty, dst_mcv, src_mcv),
55595573
5560 .mul => try self.genBinOpMir(switch (lhs_ty.zigTypeTag()) {5574 .mul => try self.genBinOpMir(switch (lhs_ty.zigTypeTag()) {
5561 else => return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }),5575 else => return self.fail("TODO implement genBinOp for {s} {}", .{
5576 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5577 }),
5562 .Float => switch (lhs_ty.floatBits(self.target.*)) {5578 .Float => switch (lhs_ty.floatBits(self.target.*)) {
5563 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse))5579 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse))
5564 .mulss5580 .mulss
...@@ -5761,9 +5777,13 @@ fn genBinOp(...@@ -5761,9 +5777,13 @@ fn genBinOp(
5761 .max => .maxsd,5777 .max => .maxsd,
5762 else => unreachable,5778 else => unreachable,
5763 },5779 },
5764 else => return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }),5780 else => return self.fail("TODO implement genBinOp for {s} {}", .{
5781 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5782 }),
5765 }, lhs_ty, dst_mcv, src_mcv),5783 }, lhs_ty, dst_mcv, src_mcv),
5766 else => return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }),5784 else => return self.fail("TODO implement genBinOp for {s} {}", .{
5785 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5786 }),
5767 },5787 },
57685788
5769 else => unreachable,5789 else => unreachable,
...@@ -5802,8 +5822,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s...@@ -5802,8 +5822,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
5802 .Float => {5822 .Float => {
5803 if (!Target.x86.featureSetHas(self.target.cpu.features, .sse))5823 if (!Target.x86.featureSetHas(self.target.cpu.features, .sse))
5804 return self.fail("TODO genBinOpMir for {s} {} without sse", .{5824 return self.fail("TODO genBinOpMir for {s} {} without sse", .{
5805 @tagName(mir_tag),5825 @tagName(mir_tag), ty.fmt(self.bin_file.options.module.?),
5806 ty.fmt(self.bin_file.options.module.?),
5807 });5826 });
5808 return self.asmRegisterRegister(mir_tag, dst_reg.to128(), src_reg.to128());5827 return self.asmRegisterRegister(mir_tag, dst_reg.to128(), src_reg.to128());
5809 },5828 },
...@@ -7588,10 +7607,11 @@ fn movMirTag(self: *Self, ty: Type) !Mir.Inst.Tag {...@@ -7588,10 +7607,11 @@ fn movMirTag(self: *Self, ty: Type) !Mir.Inst.Tag {
7588 return switch (ty.zigTypeTag()) {7607 return switch (ty.zigTypeTag()) {
7589 else => .mov,7608 else => .mov,
7590 .Float => switch (ty.floatBits(self.target.*)) {7609 .Float => switch (ty.floatBits(self.target.*)) {
7591 16 => .mov,7610 16 => unreachable, // needs special handling
7592 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse)) .movss else .mov,7611 32 => .movss,
7593 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2)) .movsd else .mov,7612 64 => .movsd,
7594 else => return self.fail("TODO movMirTag for {}", .{7613 128 => .movaps,
7614 else => return self.fail("TODO movMirTag from {}", .{
7595 ty.fmt(self.bin_file.options.module.?),7615 ty.fmt(self.bin_file.options.module.?),
7596 }),7616 }),
7597 },7617 },
...@@ -7700,8 +7720,17 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -7700,8 +7720,17 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
7700 },7720 },
7701 .register => |src_reg| if (dst_reg.id() != src_reg.id()) try self.asmRegisterRegister(7721 .register => |src_reg| if (dst_reg.id() != src_reg.id()) try self.asmRegisterRegister(
7702 if ((dst_reg.class() == .floating_point) == (src_reg.class() == .floating_point))7722 if ((dst_reg.class() == .floating_point) == (src_reg.class() == .floating_point))
7703 try self.movMirTag(ty)7723 switch (ty.zigTypeTag()) {
7724 else => .mov,
7725 .Float, .Vector => .movaps,
7726 }
7704 else switch (abi_size) {7727 else switch (abi_size) {
7728 2 => return try self.asmRegisterRegisterImmediate(
7729 if (dst_reg.class() == .floating_point) .pinsrw else .pextrw,
7730 registerAlias(dst_reg, abi_size),
7731 registerAlias(src_reg, abi_size),
7732 Immediate.u(0),
7733 ),
7705 4 => .movd,7734 4 => .movd,
7706 8 => .movq,7735 8 => .movq,
7707 else => return self.fail(7736 else => return self.fail(
...@@ -7712,18 +7741,12 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -7712,18 +7741,12 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
7712 registerAlias(dst_reg, abi_size),7741 registerAlias(dst_reg, abi_size),
7713 registerAlias(src_reg, abi_size),7742 registerAlias(src_reg, abi_size),
7714 ),7743 ),
7715 .register_offset, .indirect, .load_frame, .lea_frame => try self.asmRegisterMemory(7744 .register_offset,
7716 switch (src_mcv) {7745 .indirect,
7717 .register_offset => |reg_off| switch (reg_off.off) {7746 .load_frame,
7718 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }),7747 .lea_frame,
7719 else => .lea,7748 => {
7720 },7749 const src_mem = Memory.sib(Memory.PtrSize.fromSize(abi_size), switch (src_mcv) {
7721 .indirect, .load_frame => try self.movMirTag(ty),
7722 .lea_frame => .lea,
7723 else => unreachable,
7724 },
7725 registerAlias(dst_reg, abi_size),
7726 Memory.sib(Memory.PtrSize.fromSize(abi_size), switch (src_mcv) {
7727 .register_offset, .indirect => |reg_off| .{7750 .register_offset, .indirect => |reg_off| .{
7728 .base = .{ .reg = reg_off.reg },7751 .base = .{ .reg = reg_off.reg },
7729 .disp = reg_off.off,7752 .disp = reg_off.off,
...@@ -7733,20 +7756,51 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -7733,20 +7756,51 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
7733 .disp = frame_addr.off,7756 .disp = frame_addr.off,
7734 },7757 },
7735 else => unreachable,7758 else => unreachable,
7736 }),7759 });
7737 ),7760 if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16)
7761 try self.asmRegisterMemoryImmediate(
7762 .pinsrw,
7763 registerAlias(dst_reg, abi_size),
7764 src_mem,
7765 Immediate.u(0),
7766 )
7767 else
7768 try self.asmRegisterMemory(
7769 switch (src_mcv) {
7770 .register_offset => |reg_off| switch (reg_off.off) {
7771 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }),
7772 else => .lea,
7773 },
7774 .indirect, .load_frame => try self.movMirTag(ty),
7775 .lea_frame => .lea,
7776 else => unreachable,
7777 },
7778 registerAlias(dst_reg, abi_size),
7779 src_mem,
7780 );
7781 },
7738 .memory, .load_direct, .load_got, .load_tlv => {7782 .memory, .load_direct, .load_got, .load_tlv => {
7739 switch (src_mcv) {7783 switch (src_mcv) {
7740 .memory => |addr| if (math.cast(i32, @bitCast(i64, addr))) |small_addr|7784 .memory => |addr| if (math.cast(i32, @bitCast(i64, addr))) |small_addr| {
7741 return self.asmRegisterMemory(7785 const src_mem = Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
7742 try self.movMirTag(ty),7786 .base = .{ .reg = .ds },
7743 registerAlias(dst_reg, abi_size),7787 .disp = small_addr,
7744 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{7788 });
7745 .base = .{ .reg = .ds },7789 return if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16)
7746 .disp = small_addr,7790 self.asmRegisterMemoryImmediate(
7747 }),7791 .pinsrw,
7748 ),7792 registerAlias(dst_reg, abi_size),
7749 .load_direct => |sym_index| if (try self.movMirTag(ty) == .mov) {7793 src_mem,
7794 Immediate.u(0),
7795 )
7796 else
7797 self.asmRegisterMemory(
7798 try self.movMirTag(ty),
7799 registerAlias(dst_reg, abi_size),
7800 src_mem,
7801 );
7802 },
7803 .load_direct => |sym_index| if (!ty.isRuntimeFloat()) {
7750 const atom_index = try self.owner.getSymbolIndex(self);7804 const atom_index = try self.owner.getSymbolIndex(self);
7751 _ = try self.addInst(.{7805 _ = try self.addInst(.{
7752 .tag = .mov_linker,7806 .tag = .mov_linker,
...@@ -7767,11 +7821,22 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -7767,11 +7821,22 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
7767 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);7821 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
7768 defer self.register_manager.unlockReg(addr_lock);7822 defer self.register_manager.unlockReg(addr_lock);
77697823
7770 try self.asmRegisterMemory(7824 const src_mem = Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
7771 try self.movMirTag(ty),7825 .base = .{ .reg = addr_reg },
7772 registerAlias(dst_reg, abi_size),7826 });
7773 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .{ .reg = addr_reg } }),7827 if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16)
7774 );7828 try self.asmRegisterMemoryImmediate(
7829 .pinsrw,
7830 registerAlias(dst_reg, abi_size),
7831 src_mem,
7832 Immediate.u(0),
7833 )
7834 else
7835 try self.asmRegisterMemory(
7836 try self.movMirTag(ty),
7837 registerAlias(dst_reg, abi_size),
7838 src_mem,
7839 );
7775 },7840 },
7776 .lea_direct, .lea_got => |sym_index| {7841 .lea_direct, .lea_got => |sym_index| {
7777 const atom_index = try self.owner.getSymbolIndex(self);7842 const atom_index = try self.owner.getSymbolIndex(self);
...@@ -7864,11 +7929,25 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal...@@ -7864,11 +7929,25 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
7864 },7929 },
7865 },7930 },
7866 .eflags => |cc| try self.asmSetccMemory(Memory.sib(.byte, .{ .base = base, .disp = disp }), cc),7931 .eflags => |cc| try self.asmSetccMemory(Memory.sib(.byte, .{ .base = base, .disp = disp }), cc),
7867 .register => |reg| try self.asmMemoryRegister(7932 .register => |src_reg| {
7868 try self.movMirTag(ty),7933 const dst_mem = Memory.sib(
7869 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base, .disp = disp }),7934 Memory.PtrSize.fromSize(abi_size),
7870 registerAlias(reg, abi_size),7935 .{ .base = base, .disp = disp },
7871 ),7936 );
7937 if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16)
7938 try self.asmMemoryRegisterImmediate(
7939 .pextrw,
7940 dst_mem,
7941 registerAlias(src_reg, abi_size),
7942 Immediate.u(0),
7943 )
7944 else
7945 try self.asmMemoryRegister(
7946 try self.movMirTag(ty),
7947 dst_mem,
7948 registerAlias(src_reg, abi_size),
7949 );
7950 },
7872 .register_overflow => |ro| {7951 .register_overflow => |ro| {
7873 try self.genSetMem(7952 try self.genSetMem(
7874 base,7953 base,
...@@ -8071,8 +8150,8 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -8071,8 +8150,8 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
8071 const src_ty = self.air.typeOf(ty_op.operand);8150 const src_ty = self.air.typeOf(ty_op.operand);
80728151
8073 const result = result: {8152 const result = result: {
8074 const dst_rc = try self.regClassForType(dst_ty);8153 const dst_rc = regClassForType(dst_ty);
8075 const src_rc = try self.regClassForType(src_ty);8154 const src_rc = regClassForType(src_ty);
8076 const operand = try self.resolveInst(ty_op.operand);8155 const operand = try self.resolveInst(ty_op.operand);
8077 if (dst_rc.supersetOf(src_rc) and self.reuseOperand(inst, ty_op.operand, 0, operand))8156 if (dst_rc.supersetOf(src_rc) and self.reuseOperand(inst, ty_op.operand, 0, operand))
8078 break :result operand;8157 break :result operand;
...@@ -8127,8 +8206,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {...@@ -8127,8 +8206,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
8127 .unsigned => src_bits + 1,8206 .unsigned => src_bits + 1,
8128 }, 32), 8) catch unreachable;8207 }, 32), 8) catch unreachable;
8129 if (src_size > 8) return self.fail("TODO implement airIntToFloat from {} to {}", .{8208 if (src_size > 8) return self.fail("TODO implement airIntToFloat from {} to {}", .{
8130 src_ty.fmt(self.bin_file.options.module.?),8209 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
8131 dst_ty.fmt(self.bin_file.options.module.?),
8132 });8210 });
81338211
8134 const src_mcv = try self.resolveInst(ty_op.operand);8212 const src_mcv = try self.resolveInst(ty_op.operand);
...@@ -8141,7 +8219,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {...@@ -8141,7 +8219,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
81418219
8142 if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg);8220 if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg);
81438221
8144 const dst_reg = try self.register_manager.allocReg(inst, try self.regClassForType(dst_ty));8222 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty));
8145 const dst_mcv = MCValue{ .register = dst_reg };8223 const dst_mcv = MCValue{ .register = dst_reg };
8146 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);8224 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
8147 defer self.register_manager.unlockReg(dst_lock);8225 defer self.register_manager.unlockReg(dst_lock);
...@@ -8151,19 +8229,16 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {...@@ -8151,19 +8229,16 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
8151 .cvtsi2ss8229 .cvtsi2ss
8152 else8230 else
8153 return self.fail("TODO implement airIntToFloat from {} to {} without sse", .{8231 return self.fail("TODO implement airIntToFloat from {} to {} without sse", .{
8154 src_ty.fmt(self.bin_file.options.module.?),8232 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
8155 dst_ty.fmt(self.bin_file.options.module.?),
8156 }),8233 }),
8157 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2))8234 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2))
8158 .cvtsi2sd8235 .cvtsi2sd
8159 else8236 else
8160 return self.fail("TODO implement airIntToFloat from {} to {} without sse2", .{8237 return self.fail("TODO implement airIntToFloat from {} to {} without sse2", .{
8161 src_ty.fmt(self.bin_file.options.module.?),8238 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
8162 dst_ty.fmt(self.bin_file.options.module.?),
8163 }),8239 }),
8164 else => return self.fail("TODO implement airIntToFloat from {} to {}", .{8240 else => return self.fail("TODO implement airIntToFloat from {} to {}", .{
8165 src_ty.fmt(self.bin_file.options.module.?),8241 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
8166 dst_ty.fmt(self.bin_file.options.module.?),
8167 }),8242 }),
8168 }, dst_reg.to128(), registerAlias(src_reg, src_size));8243 }, dst_reg.to128(), registerAlias(src_reg, src_size));
81698244
src/arch/x86_64/Encoding.zig+5-1
...@@ -274,9 +274,11 @@ pub const Mnemonic = enum {...@@ -274,9 +274,11 @@ pub const Mnemonic = enum {
274 cvtsi2ss,274 cvtsi2ss,
275 divss,275 divss,
276 maxss, minss,276 maxss, minss,
277 movss,277 movaps, movss, movups,
278 mulss,278 mulss,
279 orps,279 orps,
280 pextrw,
281 pinsrw,
280 sqrtps,282 sqrtps,
281 sqrtss,283 sqrtss,
282 subss,284 subss,
...@@ -290,7 +292,9 @@ pub const Mnemonic = enum {...@@ -290,7 +292,9 @@ pub const Mnemonic = enum {
290 cvtsd2ss, cvtsi2sd, cvtss2sd,292 cvtsd2ss, cvtsi2sd, cvtss2sd,
291 divsd,293 divsd,
292 maxsd, minsd,294 maxsd, minsd,
295 movapd,
293 movq, //movd, movsd,296 movq, //movd, movsd,
297 movupd,
294 mulsd,298 mulsd,
295 orpd,299 orpd,
296 sqrtpd,300 sqrtpd,
src/arch/x86_64/Lower.zig+13
...@@ -101,9 +101,13 @@ pub fn lowerMir(lower: *Lower, inst: Mir.Inst) Error![]const Instruction {...@@ -101,9 +101,13 @@ pub fn lowerMir(lower: *Lower, inst: Mir.Inst) Error![]const Instruction {
101 .divss,101 .divss,
102 .maxss,102 .maxss,
103 .minss,103 .minss,
104 .movaps,
104 .movss,105 .movss,
106 .movups,
105 .mulss,107 .mulss,
106 .orps,108 .orps,
109 .pextrw,
110 .pinsrw,
107 .roundss,111 .roundss,
108 .sqrtps,112 .sqrtps,
109 .sqrtss,113 .sqrtss,
...@@ -198,6 +202,8 @@ fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {...@@ -198,6 +202,8 @@ fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
198 .mi_rip_u,202 .mi_rip_u,
199 .lock_mi_sib_u,203 .lock_mi_sib_u,
200 .lock_mi_rip_u,204 .lock_mi_rip_u,
205 .rmi_sib,
206 .rmi_rip,
201 .mri_sib,207 .mri_sib,
202 .mri_rip,208 .mri_rip,
203 => Immediate.u(i),209 => Immediate.u(i),
...@@ -212,6 +218,7 @@ fn mem(lower: Lower, ops: Mir.Inst.Ops, payload: u32) Memory {...@@ -212,6 +218,7 @@ fn mem(lower: Lower, ops: Mir.Inst.Ops, payload: u32) Memory {
212 return lower.mir.resolveFrameLoc(switch (ops) {218 return lower.mir.resolveFrameLoc(switch (ops) {
213 .rm_sib,219 .rm_sib,
214 .rm_sib_cc,220 .rm_sib_cc,
221 .rmi_sib,
215 .m_sib,222 .m_sib,
216 .m_sib_cc,223 .m_sib_cc,
217 .mi_sib_u,224 .mi_sib_u,
...@@ -227,6 +234,7 @@ fn mem(lower: Lower, ops: Mir.Inst.Ops, payload: u32) Memory {...@@ -227,6 +234,7 @@ fn mem(lower: Lower, ops: Mir.Inst.Ops, payload: u32) Memory {
227234
228 .rm_rip,235 .rm_rip,
229 .rm_rip_cc,236 .rm_rip_cc,
237 .rmi_rip,
230 .m_rip,238 .m_rip,
231 .m_rip_cc,239 .m_rip_cc,
232 .mi_rip_u,240 .mi_rip_u,
...@@ -321,6 +329,11 @@ fn mirGeneric(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -321,6 +329,11 @@ fn mirGeneric(lower: *Lower, inst: Mir.Inst) Error!void {
321 .{ .reg = inst.data.rx.r },329 .{ .reg = inst.data.rx.r },
322 .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },330 .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
323 },331 },
332 .rmi_sib, .rmi_rip => &.{
333 .{ .reg = inst.data.rix.r },
334 .{ .mem = lower.mem(inst.ops, inst.data.rix.payload) },
335 .{ .imm = lower.imm(inst.ops, inst.data.rix.i) },
336 },
324 .mr_sib, .lock_mr_sib, .mr_rip, .lock_mr_rip => &.{337 .mr_sib, .lock_mr_sib, .mr_rip, .lock_mr_rip => &.{
325 .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },338 .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
326 .{ .reg = inst.data.rx.r },339 .{ .reg = inst.data.rx.r },
src/arch/x86_64/Mir.zig+14
...@@ -182,12 +182,20 @@ pub const Inst = struct {...@@ -182,12 +182,20 @@ pub const Inst = struct {
182 maxss,182 maxss,
183 /// Return minimum single-precision floating-point value183 /// Return minimum single-precision floating-point value
184 minss,184 minss,
185 /// Move aligned packed single-precision floating-point values
186 movaps,
185 /// Move scalar single-precision floating-point value187 /// Move scalar single-precision floating-point value
186 movss,188 movss,
189 /// Move unaligned packed single-precision floating-point values
190 movups,
187 /// Multiply scalar single-precision floating-point values191 /// Multiply scalar single-precision floating-point values
188 mulss,192 mulss,
189 /// Bitwise logical or of packed single precision floating-point values193 /// Bitwise logical or of packed single precision floating-point values
190 orps,194 orps,
195 /// Extract word
196 pextrw,
197 /// Insert word
198 pinsrw,
191 /// Round scalar single-precision floating-point values199 /// Round scalar single-precision floating-point values
192 roundss,200 roundss,
193 /// Square root of scalar single precision floating-point value201 /// Square root of scalar single precision floating-point value
...@@ -346,6 +354,12 @@ pub const Inst = struct {...@@ -346,6 +354,12 @@ pub const Inst = struct {
346 /// Register, memory (RIP) operands with condition code (CC).354 /// Register, memory (RIP) operands with condition code (CC).
347 /// Uses `rx_cc` payload.355 /// Uses `rx_cc` payload.
348 rm_rip_cc,356 rm_rip_cc,
357 /// Register, memory (SIB), immediate (byte) operands.
358 /// Uses `rix` payload with extra data of type `MemorySib`.
359 rmi_sib,
360 /// Register, memory (RIP), immediate (byte) operands.
361 /// Uses `rix` payload with extra data of type `MemoryRip`.
362 rmi_rip,
349 /// Single memory (SIB) operand.363 /// Single memory (SIB) operand.
350 /// Uses `payload` with extra data of type `MemorySib`.364 /// Uses `payload` with extra data of type `MemorySib`.
351 m_sib,365 m_sib,
src/arch/x86_64/encodings.zig+18
...@@ -847,9 +847,15 @@ pub const table = [_]Entry{...@@ -847,9 +847,15 @@ pub const table = [_]Entry{
847847
848 .{ .minss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5d }, 0, .sse },848 .{ .minss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5d }, 0, .sse },
849849
850 .{ .movaps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x28 }, 0, .sse },
851 .{ .movaps, .mr, &.{ .xmm_m128, .xmm }, &.{ 0x0f, 0x29 }, 0, .sse },
852
850 .{ .movss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x10 }, 0, .sse },853 .{ .movss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x10 }, 0, .sse },
851 .{ .movss, .mr, &.{ .xmm_m32, .xmm }, &.{ 0xf3, 0x0f, 0x11 }, 0, .sse },854 .{ .movss, .mr, &.{ .xmm_m32, .xmm }, &.{ 0xf3, 0x0f, 0x11 }, 0, .sse },
852855
856 .{ .movups, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x10 }, 0, .sse },
857 .{ .movups, .mr, &.{ .xmm_m128, .xmm }, &.{ 0x0f, 0x11 }, 0, .sse },
858
853 .{ .mulss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x59 }, 0, .sse },859 .{ .mulss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x59 }, 0, .sse },
854860
855 .{ .orps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x56 }, 0, .sse },861 .{ .orps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x56 }, 0, .sse },
...@@ -885,6 +891,9 @@ pub const table = [_]Entry{...@@ -885,6 +891,9 @@ pub const table = [_]Entry{
885891
886 .{ .minsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5d }, 0, .sse2 },892 .{ .minsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5d }, 0, .sse2 },
887893
894 .{ .movapd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x28 }, 0, .sse2 },
895 .{ .movapd, .mr, &.{ .xmm_m128, .xmm }, &.{ 0x66, 0x0f, 0x29 }, 0, .sse2 },
896
888 .{ .movd, .rm, &.{ .xmm, .rm32 }, &.{ 0x66, 0x0f, 0x6e }, 0, .sse2 },897 .{ .movd, .rm, &.{ .xmm, .rm32 }, &.{ 0x66, 0x0f, 0x6e }, 0, .sse2 },
889 .{ .movd, .mr, &.{ .rm32, .xmm }, &.{ 0x66, 0x0f, 0x7e }, 0, .sse2 },898 .{ .movd, .mr, &.{ .rm32, .xmm }, &.{ 0x66, 0x0f, 0x7e }, 0, .sse2 },
890899
...@@ -894,10 +903,17 @@ pub const table = [_]Entry{...@@ -894,10 +903,17 @@ pub const table = [_]Entry{
894 .{ .movq, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0x7e }, 0, .sse2 },903 .{ .movq, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0x7e }, 0, .sse2 },
895 .{ .movq, .mr, &.{ .xmm_m64, .xmm }, &.{ 0x66, 0x0f, 0xd6 }, 0, .sse2 },904 .{ .movq, .mr, &.{ .xmm_m64, .xmm }, &.{ 0x66, 0x0f, 0xd6 }, 0, .sse2 },
896905
906 .{ .movupd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x10 }, 0, .sse2 },
907 .{ .movupd, .mr, &.{ .xmm_m128, .xmm }, &.{ 0x66, 0x0f, 0x11 }, 0, .sse2 },
908
897 .{ .mulsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x59 }, 0, .sse2 },909 .{ .mulsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x59 }, 0, .sse2 },
898910
899 .{ .orpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x56 }, 0, .sse2 },911 .{ .orpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x56 }, 0, .sse2 },
900912
913 .{ .pextrw, .mri, &.{ .r16, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0xc5 }, 0, .sse2 },
914
915 .{ .pinsrw, .rmi, &.{ .xmm, .rm16, .imm8 }, &.{ 0x66, 0x0f, 0xc4 }, 0, .sse2 },
916
901 .{ .sqrtpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x51 }, 0, .sse2 },917 .{ .sqrtpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x51 }, 0, .sse2 },
902 .{ .sqrtsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x51 }, 0, .sse2 },918 .{ .sqrtsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x51 }, 0, .sse2 },
903919
...@@ -911,6 +927,8 @@ pub const table = [_]Entry{...@@ -911,6 +927,8 @@ pub const table = [_]Entry{
911 .{ .xorpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x57 }, 0, .sse2 },927 .{ .xorpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x57 }, 0, .sse2 },
912928
913 // SSE4.1929 // SSE4.1
930 .{ .pextrw, .mri, &.{ .rm16, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x15 }, 0, .sse4_1 },
931
914 .{ .roundss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0a }, 0, .sse4_1 },932 .{ .roundss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0a }, 0, .sse4_1 },
915 .{ .roundsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0b }, 0, .sse4_1 },933 .{ .roundsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0b }, 0, .sse4_1 },
916};934};
test/behavior/vector.zig-6
...@@ -133,7 +133,6 @@ test "vector bit operators" {...@@ -133,7 +133,6 @@ test "vector bit operators" {
133}133}
134134
135test "implicit cast vector to array" {135test "implicit cast vector to array" {
136 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
138 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO138 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -151,7 +150,6 @@ test "implicit cast vector to array" {...@@ -151,7 +150,6 @@ test "implicit cast vector to array" {
151}150}
152151
153test "array to vector" {152test "array to vector" {
154 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO153 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
156 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
157 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO155 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -321,7 +319,6 @@ test "load vector elements via comptime index" {...@@ -321,7 +319,6 @@ test "load vector elements via comptime index" {
321 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO319 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
322 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO320 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
323 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO321 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
324 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
325322
326 const S = struct {323 const S = struct {
327 fn doTheTest() !void {324 fn doTheTest() !void {
...@@ -343,7 +340,6 @@ test "store vector elements via comptime index" {...@@ -343,7 +340,6 @@ test "store vector elements via comptime index" {
343 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO340 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
344 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO341 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
345 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO342 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
346 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
347343
348 const S = struct {344 const S = struct {
349 fn doTheTest() !void {345 fn doTheTest() !void {
...@@ -371,7 +367,6 @@ test "load vector elements via runtime index" {...@@ -371,7 +367,6 @@ test "load vector elements via runtime index" {
371 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO367 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
372 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO368 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
373 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO369 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
374 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
375370
376 const S = struct {371 const S = struct {
377 fn doTheTest() !void {372 fn doTheTest() !void {
...@@ -393,7 +388,6 @@ test "store vector elements via runtime index" {...@@ -393,7 +388,6 @@ test "store vector elements via runtime index" {
393 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO388 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
394 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO389 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
395 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO390 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
396 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
397391
398 const S = struct {392 const S = struct {
399 fn doTheTest() !void {393 fn doTheTest() !void {