authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-06 03:07:14-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-07 00:29:17-04:00
log20b4401cdef1baa377276ecae31f266cf85d4d2e
treed997c575701d7b7314b5f15bbd8933311dfe5904
parent5aeb13c3500f2244efe916a88278a86692dfc400

x86_64: implement negation and `@abs` for `f80`

Also implement live-outs since the x87 requires so much care around liveness tracking.

7 files changed, 337 insertions(+), 221 deletions(-)

src/arch/x86_64/CodeGen.zig+313-207
...@@ -47,10 +47,6 @@ const RegisterManager = abi.RegisterManager;...@@ -47,10 +47,6 @@ const RegisterManager = abi.RegisterManager;
47const RegisterLock = RegisterManager.RegisterLock;47const RegisterLock = RegisterManager.RegisterLock;
48const FrameIndex = bits.FrameIndex;48const FrameIndex = bits.FrameIndex;
4949
50const gp = abi.RegisterClass.gp;
51const x87 = abi.RegisterClass.x87;
52const sse = abi.RegisterClass.sse;
53
54const InnerError = CodeGenError || error{OutOfRegisters};50const InnerError = CodeGenError || error{OutOfRegisters};
5551
56gpa: Allocator,52gpa: Allocator,
...@@ -620,6 +616,7 @@ const InstTracking = struct {...@@ -620,6 +616,7 @@ const InstTracking = struct {
620 }616 }
621617
622 fn die(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void {618 fn die(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void {
619 if (self.short == .dead) return;
623 try function.freeValue(self.short);620 try function.freeValue(self.short);
624 self.short = .{ .dead = function.scope_generation };621 self.short = .{ .dead = function.scope_generation };
625 tracking_log.debug("%{d} => {} (death)", .{ inst, self.* });622 tracking_log.debug("%{d} => {} (death)", .{ inst, self.* });
...@@ -635,6 +632,40 @@ const InstTracking = struct {...@@ -635,6 +632,40 @@ const InstTracking = struct {
635 tracking_log.debug("%{d} => {} (reuse %{d})", .{ new_inst, self.*, old_inst });632 tracking_log.debug("%{d} => {} (reuse %{d})", .{ new_inst, self.*, old_inst });
636 }633 }
637634
635 fn liveOut(self: *InstTracking, function: *Self, inst: Air.Inst.Index) void {
636 for (self.short.getRegs()) |reg| {
637 if (function.register_manager.isRegFree(reg)) {
638 tracking_log.debug("%{d} => {} (live-out)", .{ inst, self.* });
639 continue;
640 }
641
642 const index = RegisterManager.indexOfRegIntoTracked(reg).?;
643 const tracked_inst = function.register_manager.registers[index];
644 const tracking = function.getResolvedInstValue(tracked_inst);
645
646 // Disable death.
647 var found_reg = false;
648 var remaining_reg: Register = .none;
649 for (tracking.short.getRegs()) |tracked_reg| if (tracked_reg.id() == reg.id()) {
650 assert(!found_reg);
651 found_reg = true;
652 } else {
653 assert(remaining_reg == .none);
654 remaining_reg = tracked_reg;
655 };
656 assert(found_reg);
657 tracking.short = switch (remaining_reg) {
658 .none => .{ .dead = function.scope_generation },
659 else => .{ .register = remaining_reg },
660 };
661
662 // Perform side-effects of freeValue manually.
663 function.register_manager.freeReg(reg);
664
665 tracking_log.debug("%{d} => {} (live-out %{d})", .{ inst, self.*, tracked_inst });
666 }
667 }
668
638 pub fn format(669 pub fn format(
639 self: InstTracking,670 self: InstTracking,
640 comptime _: []const u8,671 comptime _: []const u8,
...@@ -1144,7 +1175,7 @@ fn asmSetccRegister(self: *Self, reg: Register, cc: bits.Condition) !void {...@@ -1144,7 +1175,7 @@ fn asmSetccRegister(self: *Self, reg: Register, cc: bits.Condition) !void {
1144 } },1175 } },
1145 .z_and_np, .nz_or_p => .{ .rr = .{1176 .z_and_np, .nz_or_p => .{ .rr = .{
1146 .r1 = reg,1177 .r1 = reg,
1147 .r2 = (try self.register_manager.allocReg(null, gp)).to8(),1178 .r2 = (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to8(),
1148 } },1179 } },
1149 },1180 },
1150 });1181 });
...@@ -1184,7 +1215,7 @@ fn asmSetccMemory(self: *Self, m: Memory, cc: bits.Condition) !void {...@@ -1184,7 +1215,7 @@ fn asmSetccMemory(self: *Self, m: Memory, cc: bits.Condition) !void {
1184 .payload = payload,1215 .payload = payload,
1185 } },1216 } },
1186 .z_and_np, .nz_or_p => .{ .rx = .{1217 .z_and_np, .nz_or_p => .{ .rx = .{
1187 .r1 = (try self.register_manager.allocReg(null, gp)).to8(),1218 .r1 = (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to8(),
1188 .payload = payload,1219 .payload = payload,
1189 } },1220 } },
1190 },1221 },
...@@ -2087,7 +2118,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -2087,7 +2118,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
2087 var exitlude_jump_relocs = try self.gpa.alloc(u32, enum_ty.enumFieldCount(mod));2118 var exitlude_jump_relocs = try self.gpa.alloc(u32, enum_ty.enumFieldCount(mod));
2088 defer self.gpa.free(exitlude_jump_relocs);2119 defer self.gpa.free(exitlude_jump_relocs);
20892120
2090 const data_reg = try self.register_manager.allocReg(null, gp);2121 const data_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
2091 const data_lock = self.register_manager.lockRegAssumeUnused(data_reg);2122 const data_lock = self.register_manager.lockRegAssumeUnused(data_reg);
2092 defer self.register_manager.unlockReg(data_lock);2123 defer self.register_manager.unlockReg(data_lock);
2093 try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty });2124 try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty });
...@@ -2357,7 +2388,7 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b...@@ -2357,7 +2388,7 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b
2357 },2388 },
2358 else => 8,2389 else => 8,
2359 })) {2390 })) {
2360 if (self.register_manager.tryAllocReg(inst, regClassForType(ty, mod))) |reg| {2391 if (self.register_manager.tryAllocReg(inst, self.regClassForType(ty))) |reg| {
2361 return MCValue{ .register = registerAlias(reg, abi_size) };2392 return MCValue{ .register = registerAlias(reg, abi_size) };
2362 }2393 }
2363 }2394 }
...@@ -2367,10 +2398,15 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b...@@ -2367,10 +2398,15 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b
2367 return .{ .load_frame = .{ .index = frame_index } };2398 return .{ .load_frame = .{ .index = frame_index } };
2368}2399}
23692400
2370fn regClassForType(ty: Type, mod: *Module) RegisterManager.RegisterBitSet {2401fn regClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet {
2402 const mod = self.bin_file.options.module.?;
2371 return switch (ty.zigTypeTag(mod)) {2403 return switch (ty.zigTypeTag(mod)) {
2372 .Float, .Vector => sse,2404 .Float => switch (ty.floatBits(self.target.*)) {
2373 else => gp,2405 80 => abi.RegisterClass.x87,
2406 else => abi.RegisterClass.sse,
2407 },
2408 .Vector => abi.RegisterClass.sse,
2409 else => abi.RegisterClass.gp,
2374 };2410 };
2375}2411}
23762412
...@@ -2510,8 +2546,7 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void {...@@ -2510,8 +2546,7 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void {
2510/// allocated. A second call to `copyToTmpRegister` may return the same register.2546/// allocated. A second call to `copyToTmpRegister` may return the same register.
2511/// This can have a side effect of spilling instructions to the stack to free up a register.2547/// This can have a side effect of spilling instructions to the stack to free up a register.
2512fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {2548fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
2513 const mod = self.bin_file.options.module.?;2549 const reg = try self.register_manager.allocReg(null, self.regClassForType(ty));
2514 const reg = try self.register_manager.allocReg(null, regClassForType(ty, mod));
2515 try self.genSetReg(reg, ty, mcv);2550 try self.genSetReg(reg, ty, mcv);
2516 return reg;2551 return reg;
2517}2552}
...@@ -2526,8 +2561,7 @@ fn copyToRegisterWithInstTracking(...@@ -2526,8 +2561,7 @@ fn copyToRegisterWithInstTracking(
2526 ty: Type,2561 ty: Type,
2527 mcv: MCValue,2562 mcv: MCValue,
2528) !MCValue {2563) !MCValue {
2529 const mod = self.bin_file.options.module.?;2564 const reg: Register = try self.register_manager.allocReg(reg_owner, self.regClassForType(ty));
2530 const reg: Register = try self.register_manager.allocReg(reg_owner, regClassForType(ty, mod));
2531 try self.genSetReg(reg, ty, mcv);2565 try self.genSetReg(reg, ty, mcv);
2532 return MCValue{ .register = reg };2566 return MCValue{ .register = reg };
2533}2567}
...@@ -3084,7 +3118,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3084,7 +3118,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
3084 };3118 };
3085 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);3119 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
30863120
3087 const limit_reg = try self.register_manager.allocReg(null, gp);3121 const limit_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
3088 const limit_mcv = MCValue{ .register = limit_reg };3122 const limit_mcv = MCValue{ .register = limit_reg };
3089 const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg);3123 const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg);
3090 defer self.register_manager.unlockReg(limit_lock);3124 defer self.register_manager.unlockReg(limit_lock);
...@@ -3167,7 +3201,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3167,7 +3201,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
3167 };3201 };
3168 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);3202 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
31693203
3170 const limit_reg = try self.register_manager.allocReg(null, gp);3204 const limit_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
3171 const limit_mcv = MCValue{ .register = limit_reg };3205 const limit_mcv = MCValue{ .register = limit_reg };
3172 const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg);3206 const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg);
3173 defer self.register_manager.unlockReg(limit_lock);3207 defer self.register_manager.unlockReg(limit_lock);
...@@ -3245,7 +3279,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3245,7 +3279,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
3245 };3279 };
3246 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);3280 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
32473281
3248 const limit_reg = try self.register_manager.allocReg(null, gp);3282 const limit_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
3249 const limit_mcv = MCValue{ .register = limit_reg };3283 const limit_mcv = MCValue{ .register = limit_reg };
3250 const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg);3284 const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg);
3251 defer self.register_manager.unlockReg(limit_lock);3285 defer self.register_manager.unlockReg(limit_lock);
...@@ -3433,7 +3467,8 @@ fn genSetFrameTruncatedOverflowCompare(...@@ -3433,7 +3467,8 @@ fn genSetFrameTruncatedOverflowCompare(
34333467
3434 const rest_ty = try mod.intType(.unsigned, int_info.bits - hi_limb_bits);3468 const rest_ty = try mod.intType(.unsigned, int_info.bits - hi_limb_bits);
34353469
3436 const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }, gp);3470 const temp_regs =
3471 try self.register_manager.allocRegs(3, .{ null, null, null }, abi.RegisterClass.gp);
3437 const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs);3472 const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs);
3438 defer for (temp_locks) |lock| self.register_manager.unlockReg(lock);3473 defer for (temp_locks) |lock| self.register_manager.unlockReg(lock);
34393474
...@@ -3851,7 +3886,7 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3851,7 +3886,7 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
3851 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);3886 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
3852 defer self.register_manager.unlockReg(src_lock);3887 defer self.register_manager.unlockReg(src_lock);
38533888
3854 const dst_reg = try self.register_manager.allocReg(inst, gp);3889 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
3855 const dst_mcv = MCValue{ .register = dst_reg };3890 const dst_mcv = MCValue{ .register = dst_reg };
3856 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);3891 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
3857 defer self.register_manager.unlockReg(dst_lock);3892 defer self.register_manager.unlockReg(dst_lock);
...@@ -3891,7 +3926,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3891,7 +3926,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
3891 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))3926 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
3892 src_reg3927 src_reg
3893 else3928 else
3894 try self.register_manager.allocReg(inst, gp);3929 try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
3895 const dst_mcv = MCValue{ .register = dst_reg };3930 const dst_mcv = MCValue{ .register = dst_reg };
3896 const dst_lock = self.register_manager.lockReg(dst_reg);3931 const dst_lock = self.register_manager.lockReg(dst_reg);
3897 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);3932 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
...@@ -3942,7 +3977,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -3942,7 +3977,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
3942 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))3977 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
3943 src_reg3978 src_reg
3944 else3979 else
3945 try self.register_manager.allocReg(inst, gp);3980 try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
3946 const dst_lock = self.register_manager.lockReg(dst_reg);3981 const dst_lock = self.register_manager.lockReg(dst_reg);
3947 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);3982 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
39483983
...@@ -4115,7 +4150,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4115,7 +4150,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
4115 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))4150 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
4116 src_reg4151 src_reg
4117 else4152 else
4118 try self.register_manager.allocReg(inst, gp);4153 try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
4119 const dst_mcv = MCValue{ .register = dst_reg };4154 const dst_mcv = MCValue{ .register = dst_reg };
4120 const dst_lock = self.register_manager.lockReg(dst_reg);4155 const dst_lock = self.register_manager.lockReg(dst_reg);
4121 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);4156 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
...@@ -4152,7 +4187,7 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi...@@ -4152,7 +4187,7 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi
4152 .immediate => |imm| {4187 .immediate => |imm| {
4153 // Optimisation: if index MCValue is an immediate, we can multiply in `comptime`4188 // Optimisation: if index MCValue is an immediate, we can multiply in `comptime`
4154 // and set the register directly to the scaled offset as an immediate.4189 // and set the register directly to the scaled offset as an immediate.
4155 const reg = try self.register_manager.allocReg(null, gp);4190 const reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
4156 try self.genSetReg(reg, index_ty, .{ .immediate = imm * elem_size });4191 try self.genSetReg(reg, index_ty, .{ .immediate = imm * elem_size });
4157 break :blk reg;4192 break :blk reg;
4158 },4193 },
...@@ -4192,7 +4227,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {...@@ -4192,7 +4227,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
4192 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);4227 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
4193 defer self.register_manager.unlockReg(offset_reg_lock);4228 defer self.register_manager.unlockReg(offset_reg_lock);
41944229
4195 const addr_reg = try self.register_manager.allocReg(null, gp);4230 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
4196 try self.genSetReg(addr_reg, Type.usize, slice_mcv);4231 try self.genSetReg(addr_reg, Type.usize, slice_mcv);
4197 // TODO we could allocate register here, but need to expect addr register and potentially4232 // TODO we could allocate register here, but need to expect addr register and potentially
4198 // offset register.4233 // offset register.
...@@ -4249,7 +4284,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -4249,7 +4284,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
4249 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);4284 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
4250 defer self.register_manager.unlockReg(offset_reg_lock);4285 defer self.register_manager.unlockReg(offset_reg_lock);
42514286
4252 const addr_reg = try self.register_manager.allocReg(null, gp);4287 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
4253 switch (array) {4288 switch (array) {
4254 .register => {4289 .register => {
4255 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, mod));4290 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, mod));
...@@ -4486,7 +4521,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {...@@ -4486,7 +4521,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
4486 };4521 };
4487 defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock);4522 defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock);
44884523
4489 const dst_reg = try self.register_manager.allocReg(inst, gp);4524 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
4490 const dst_mcv = MCValue{ .register = dst_reg };4525 const dst_mcv = MCValue{ .register = dst_reg };
4491 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);4526 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
4492 defer self.register_manager.unlockReg(dst_lock);4527 defer self.register_manager.unlockReg(dst_lock);
...@@ -4510,7 +4545,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {...@@ -4510,7 +4545,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
4510 try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .immediate = extra_bits });4545 try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .immediate = extra_bits });
4511 }4546 }
4512 } else if (src_bits <= 128) {4547 } else if (src_bits <= 128) {
4513 const tmp_reg = try self.register_manager.allocReg(null, gp);4548 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
4514 const tmp_mcv = MCValue{ .register = tmp_reg };4549 const tmp_mcv = MCValue{ .register = tmp_reg };
4515 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);4550 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
4516 defer self.register_manager.unlockReg(tmp_lock);4551 defer self.register_manager.unlockReg(tmp_lock);
...@@ -4616,7 +4651,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {...@@ -4616,7 +4651,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
4616 };4651 };
4617 defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock);4652 defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock);
46184653
4619 const dst_reg = try self.register_manager.allocReg(inst, gp);4654 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
4620 const dst_mcv = MCValue{ .register = dst_reg };4655 const dst_mcv = MCValue{ .register = dst_reg };
4621 const dst_lock = self.register_manager.lockReg(dst_reg);4656 const dst_lock = self.register_manager.lockReg(dst_reg);
4622 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);4657 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
...@@ -4643,7 +4678,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {...@@ -4643,7 +4678,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
4643 } else mat_src_mcv;4678 } else mat_src_mcv;
4644 try self.genBinOpMir(.{ ._, .tzcnt }, wide_ty, dst_mcv, masked_mcv);4679 try self.genBinOpMir(.{ ._, .tzcnt }, wide_ty, dst_mcv, masked_mcv);
4645 } else if (src_bits <= 128) {4680 } else if (src_bits <= 128) {
4646 const tmp_reg = try self.register_manager.allocReg(null, gp);4681 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
4647 const tmp_mcv = MCValue{ .register = tmp_reg };4682 const tmp_mcv = MCValue{ .register = tmp_reg };
4648 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);4683 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
4649 defer self.register_manager.unlockReg(tmp_lock);4684 defer self.register_manager.unlockReg(tmp_lock);
...@@ -4718,7 +4753,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {...@@ -4718,7 +4753,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
4718 if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))4753 if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
4719 src_mcv4754 src_mcv
4720 else4755 else
4721 .{ .register = try self.register_manager.allocReg(inst, gp) };4756 .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.gp) };
47224757
4723 const popcnt_ty = if (src_abi_size > 1) src_ty else Type.u16;4758 const popcnt_ty = if (src_abi_size > 1) src_ty else Type.u16;
4724 try self.genBinOpMir(.{ ._, .popcnt }, popcnt_ty, dst_mcv, mat_src_mcv);4759 try self.genBinOpMir(.{ ._, .popcnt }, popcnt_ty, dst_mcv, mat_src_mcv);
...@@ -4739,7 +4774,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {...@@ -4739,7 +4774,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
4739 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);4774 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
4740 defer self.register_manager.unlockReg(dst_lock);4775 defer self.register_manager.unlockReg(dst_lock);
47414776
4742 const tmp_reg = try self.register_manager.allocReg(null, gp);4777 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
4743 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);4778 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
4744 defer self.register_manager.unlockReg(tmp_lock);4779 defer self.register_manager.unlockReg(tmp_lock);
47454780
...@@ -4747,7 +4782,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {...@@ -4747,7 +4782,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
4747 const dst = registerAlias(dst_reg, src_abi_size);4782 const dst = registerAlias(dst_reg, src_abi_size);
4748 const tmp = registerAlias(tmp_reg, src_abi_size);4783 const tmp = registerAlias(tmp_reg, src_abi_size);
4749 const imm = if (src_abi_size > 4)4784 const imm = if (src_abi_size > 4)
4750 try self.register_manager.allocReg(null, gp)4785 try self.register_manager.allocReg(null, abi.RegisterClass.gp)
4751 else4786 else
4752 undefined;4787 undefined;
47534788
...@@ -4848,7 +4883,7 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m...@@ -4848,7 +4883,7 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m
4848 const dst_mcv: MCValue = if (mem_ok)4883 const dst_mcv: MCValue = if (mem_ok)
4849 try self.allocRegOrMem(inst, true)4884 try self.allocRegOrMem(inst, true)
4850 else4885 else
4851 .{ .register = try self.register_manager.allocReg(inst, gp) };4886 .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.gp) };
4852 if (dst_mcv.isRegister()) {4887 if (dst_mcv.isRegister()) {
4853 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_mcv.register);4888 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_mcv.register);
4854 defer self.register_manager.unlockReg(dst_lock);4889 defer self.register_manager.unlockReg(dst_lock);
...@@ -4863,7 +4898,7 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m...@@ -4863,7 +4898,7 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m
4863 return dst_mcv;4898 return dst_mcv;
4864 }4899 }
48654900
4866 const dst_reg = try self.register_manager.allocReg(inst, gp);4901 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
4867 const dst_mcv = MCValue{ .register = dst_reg };4902 const dst_mcv = MCValue{ .register = dst_reg };
4868 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);4903 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
4869 defer self.register_manager.unlockReg(dst_lock);4904 defer self.register_manager.unlockReg(dst_lock);
...@@ -4906,7 +4941,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {...@@ -4906,7 +4941,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
4906 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);4941 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
4907 defer self.register_manager.unlockReg(dst_lock);4942 defer self.register_manager.unlockReg(dst_lock);
49084943
4909 const tmp_reg = try self.register_manager.allocReg(null, gp);4944 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
4910 const tmp_lock = self.register_manager.lockReg(tmp_reg);4945 const tmp_lock = self.register_manager.lockReg(tmp_reg);
4911 defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock);4946 defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock);
49124947
...@@ -4914,7 +4949,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {...@@ -4914,7 +4949,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
4914 const dst = registerAlias(dst_reg, src_abi_size);4949 const dst = registerAlias(dst_reg, src_abi_size);
4915 const tmp = registerAlias(tmp_reg, src_abi_size);4950 const tmp = registerAlias(tmp_reg, src_abi_size);
4916 const imm = if (src_abi_size > 4)4951 const imm = if (src_abi_size > 4)
4917 try self.register_manager.allocReg(null, gp)4952 try self.register_manager.allocReg(null, abi.RegisterClass.gp)
4918 else4953 else
4919 undefined;4954 undefined;
49204955
...@@ -5006,109 +5041,133 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {...@@ -5006,109 +5041,133 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
5006fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) !void {5041fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) !void {
5007 const mod = self.bin_file.options.module.?;5042 const mod = self.bin_file.options.module.?;
5008 const tag = self.air.instructions.items(.tag)[inst];5043 const tag = self.air.instructions.items(.tag)[inst];
5009 const abi_size: u32 = switch (ty.abiSize(mod)) {
5010 1...16 => 16,
5011 17...32 => 32,
5012 else => return self.fail("TODO implement floatSign for {}", .{
5013 ty.fmt(mod),
5014 }),
5015 };
5016 const scalar_bits = ty.scalarType(mod).floatBits(self.target.*);
5017 if (scalar_bits == 80) return self.fail("TODO implement floatSign for {}", .{
5018 ty.fmt(mod),
5019 });
50205044
5021 const src_mcv = try self.resolveInst(operand);5045 const result = result: {
5022 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;5046 const scalar_bits = ty.scalarType(mod).floatBits(self.target.*);
5023 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);5047 if (scalar_bits == 80) {
5048 if (ty.zigTypeTag(mod) != .Float) return self.fail("TODO implement floatSign for {}", .{
5049 ty.fmt(mod),
5050 });
50245051
5025 const dst_mcv: MCValue = if (src_mcv.isRegister() and self.reuseOperand(inst, operand, 0, src_mcv))5052 const src_mcv = try self.resolveInst(operand);
5026 src_mcv5053 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
5027 else if (self.hasFeature(.avx))5054 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
5028 .{ .register = try self.register_manager.allocReg(inst, sse) }
5029 else
5030 try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
5031 const dst_reg = dst_mcv.getReg().?;
5032 const dst_lock = self.register_manager.lockReg(dst_reg);
5033 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
50345055
5035 const vec_ty = try mod.vectorType(.{5056 const dst_mcv: MCValue = .{ .register = .st0 };
5036 .len = @divExact(abi_size * 8, scalar_bits),5057 if (std.meta.eql(src_mcv, dst_mcv) and self.reuseOperand(inst, operand, 0, src_mcv))
5037 .child = (try mod.intType(.signed, scalar_bits)).ip_index,5058 try self.register_manager.getReg(.st0, inst);
5038 });
50395059
5040 const sign_val = switch (tag) {5060 try self.genCopy(ty, dst_mcv, src_mcv);
5041 .neg => try vec_ty.minInt(mod, vec_ty),5061 switch (tag) {
5042 .abs => try vec_ty.maxInt(mod, vec_ty),5062 .neg => try self.asmOpOnly(.{ .f_, .chs }),
5043 else => unreachable,5063 .abs => try self.asmOpOnly(.{ .f_, .abs }),
5044 };5064 else => unreachable,
5065 }
5066 break :result dst_mcv;
5067 }
50455068
5046 const sign_mcv = try self.genTypedValue(.{ .ty = vec_ty, .val = sign_val });5069 const abi_size: u32 = switch (ty.abiSize(mod)) {
5047 const sign_mem = if (sign_mcv.isMemory())5070 1...16 => 16,
5048 sign_mcv.mem(Memory.PtrSize.fromSize(abi_size))5071 17...32 => 32,
5049 else5072 else => return self.fail("TODO implement floatSign for {}", .{
5050 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{5073 ty.fmt(mod),
5051 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, sign_mcv.address()) },5074 }),
5075 };
5076
5077 const src_mcv = try self.resolveInst(operand);
5078 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
5079 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
5080
5081 const dst_mcv: MCValue = if (src_mcv.isRegister() and
5082 self.reuseOperand(inst, operand, 0, src_mcv))
5083 src_mcv
5084 else if (self.hasFeature(.avx))
5085 .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.sse) }
5086 else
5087 try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
5088 const dst_reg = dst_mcv.getReg().?;
5089 const dst_lock = self.register_manager.lockReg(dst_reg);
5090 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
5091
5092 const vec_ty = try mod.vectorType(.{
5093 .len = @divExact(abi_size * 8, scalar_bits),
5094 .child = (try mod.intType(.signed, scalar_bits)).ip_index,
5052 });5095 });
50535096
5054 if (self.hasFeature(.avx)) try self.asmRegisterRegisterMemory(5097 const sign_val = switch (tag) {
5055 switch (scalar_bits) {5098 .neg => try vec_ty.minInt(mod, vec_ty),
5056 16, 128 => if (abi_size <= 16 or self.hasFeature(.avx2)) switch (tag) {5099 .abs => try vec_ty.maxInt(mod, vec_ty),
5057 .neg => .{ .vp_, .xor },
5058 .abs => .{ .vp_, .@"and" },
5059 else => unreachable,
5060 } else switch (tag) {
5061 .neg => .{ .v_ps, .xor },
5062 .abs => .{ .v_ps, .@"and" },
5063 else => unreachable,
5064 },
5065 32 => switch (tag) {
5066 .neg => .{ .v_ps, .xor },
5067 .abs => .{ .v_ps, .@"and" },
5068 else => unreachable,
5069 },
5070 64 => switch (tag) {
5071 .neg => .{ .v_pd, .xor },
5072 .abs => .{ .v_pd, .@"and" },
5073 else => unreachable,
5074 },
5075 80 => return self.fail("TODO implement floatSign for {}", .{
5076 ty.fmt(self.bin_file.options.module.?),
5077 }),
5078 else => unreachable,5100 else => unreachable,
5079 },5101 };
5080 registerAlias(dst_reg, abi_size),5102
5081 registerAlias(if (src_mcv.isRegister())5103 const sign_mcv = try self.genTypedValue(.{ .ty = vec_ty, .val = sign_val });
5082 src_mcv.getReg().?5104 const sign_mem = if (sign_mcv.isMemory())
5105 sign_mcv.mem(Memory.PtrSize.fromSize(abi_size))
5083 else5106 else
5084 try self.copyToTmpRegister(ty, src_mcv), abi_size),5107 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
5085 sign_mem,5108 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, sign_mcv.address()) },
5086 ) else try self.asmRegisterMemory(5109 });
5087 switch (scalar_bits) {5110
5088 16, 128 => switch (tag) {5111 if (self.hasFeature(.avx)) try self.asmRegisterRegisterMemory(
5089 .neg => .{ .p_, .xor },5112 switch (scalar_bits) {
5090 .abs => .{ .p_, .@"and" },5113 16, 128 => if (abi_size <= 16 or self.hasFeature(.avx2)) switch (tag) {
5091 else => unreachable,5114 .neg => .{ .vp_, .xor },
5092 },5115 .abs => .{ .vp_, .@"and" },
5093 32 => switch (tag) {5116 else => unreachable,
5094 .neg => .{ ._ps, .xor },5117 } else switch (tag) {
5095 .abs => .{ ._ps, .@"and" },5118 .neg => .{ .v_ps, .xor },
5119 .abs => .{ .v_ps, .@"and" },
5120 else => unreachable,
5121 },
5122 32 => switch (tag) {
5123 .neg => .{ .v_ps, .xor },
5124 .abs => .{ .v_ps, .@"and" },
5125 else => unreachable,
5126 },
5127 64 => switch (tag) {
5128 .neg => .{ .v_pd, .xor },
5129 .abs => .{ .v_pd, .@"and" },
5130 else => unreachable,
5131 },
5132 80 => return self.fail("TODO implement floatSign for {}", .{
5133 ty.fmt(self.bin_file.options.module.?),
5134 }),
5096 else => unreachable,5135 else => unreachable,
5097 },5136 },
5098 64 => switch (tag) {5137 registerAlias(dst_reg, abi_size),
5099 .neg => .{ ._pd, .xor },5138 registerAlias(if (src_mcv.isRegister())
5100 .abs => .{ ._pd, .@"and" },5139 src_mcv.getReg().?
5140 else
5141 try self.copyToTmpRegister(ty, src_mcv), abi_size),
5142 sign_mem,
5143 ) else try self.asmRegisterMemory(
5144 switch (scalar_bits) {
5145 16, 128 => switch (tag) {
5146 .neg => .{ .p_, .xor },
5147 .abs => .{ .p_, .@"and" },
5148 else => unreachable,
5149 },
5150 32 => switch (tag) {
5151 .neg => .{ ._ps, .xor },
5152 .abs => .{ ._ps, .@"and" },
5153 else => unreachable,
5154 },
5155 64 => switch (tag) {
5156 .neg => .{ ._pd, .xor },
5157 .abs => .{ ._pd, .@"and" },
5158 else => unreachable,
5159 },
5160 80 => return self.fail("TODO implement floatSign for {}", .{
5161 ty.fmt(self.bin_file.options.module.?),
5162 }),
5101 else => unreachable,5163 else => unreachable,
5102 },5164 },
5103 80 => return self.fail("TODO implement floatSign for {}", .{5165 registerAlias(dst_reg, abi_size),
5104 ty.fmt(self.bin_file.options.module.?),5166 sign_mem,
5105 }),5167 );
5106 else => unreachable,5168 break :result dst_mcv;
5107 },5169 };
5108 registerAlias(dst_reg, abi_size),5170 return self.finishAir(inst, result, .{ operand, .none, .none });
5109 sign_mem,
5110 );
5111 return self.finishAir(inst, dst_mcv, .{ operand, .none, .none });
5112}5171}
51135172
5114fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {5173fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
...@@ -5292,19 +5351,43 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {...@@ -5292,19 +5351,43 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
5292 const ty = self.typeOf(un_op);5351 const ty = self.typeOf(un_op);
5293 const abi_size: u32 = @intCast(ty.abiSize(mod));5352 const abi_size: u32 = @intCast(ty.abiSize(mod));
52945353
5295 const src_mcv = try self.resolveInst(un_op);
5296 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv))
5297 src_mcv
5298 else
5299 try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
5300 const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size);
5301 const dst_lock = self.register_manager.lockReg(dst_reg);
5302 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
5303
5304 const result: MCValue = result: {5354 const result: MCValue = result: {
5355 switch (ty.zigTypeTag(mod)) {
5356 .Float => {
5357 const float_bits = ty.floatBits(self.target.*);
5358 if (switch (float_bits) {
5359 16 => !self.hasFeature(.f16c),
5360 32, 64 => false,
5361 80, 128 => true,
5362 else => unreachable,
5363 }) {
5364 var callee: ["__sqrt?".len]u8 = undefined;
5365 break :result try self.genCall(.{ .lib = .{
5366 .return_type = ty.toIntern(),
5367 .param_types = &.{ty.toIntern()},
5368 .callee = std.fmt.bufPrint(&callee, "{s}sqrt{s}", .{
5369 floatLibcAbiPrefix(ty),
5370 floatLibcAbiSuffix(ty),
5371 }) catch unreachable,
5372 } }, &.{ty}, &.{.{ .air_ref = un_op }});
5373 }
5374 },
5375 else => {},
5376 }
5377
5378 const src_mcv = try self.resolveInst(un_op);
5379 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv))
5380 src_mcv
5381 else
5382 try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
5383 const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size);
5384 const dst_lock = self.register_manager.lockReg(dst_reg);
5385 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
5386
5305 const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) {5387 const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) {
5306 .Float => switch (ty.floatBits(self.target.*)) {5388 .Float => switch (ty.floatBits(self.target.*)) {
5307 16 => if (self.hasFeature(.f16c)) {5389 16 => {
5390 assert(self.hasFeature(.f16c));
5308 const mat_src_reg = if (src_mcv.isRegister())5391 const mat_src_reg = if (src_mcv.isRegister())
5309 src_mcv.getReg().?5392 src_mcv.getReg().?
5310 else5393 else
...@@ -5318,10 +5401,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {...@@ -5318,10 +5401,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
5318 Immediate.u(0b1_00),5401 Immediate.u(0b1_00),
5319 );5402 );
5320 break :result dst_mcv;5403 break :result dst_mcv;
5321 } else null,5404 },
5322 32 => if (self.hasFeature(.avx)) .{ .v_ss, .sqrt } else .{ ._ss, .sqrt },5405 32 => if (self.hasFeature(.avx)) .{ .v_ss, .sqrt } else .{ ._ss, .sqrt },
5323 64 => if (self.hasFeature(.avx)) .{ .v_sd, .sqrt } else .{ ._sd, .sqrt },5406 64 => if (self.hasFeature(.avx)) .{ .v_sd, .sqrt } else .{ ._sd, .sqrt },
5324 80, 128 => null,
5325 else => unreachable,5407 else => unreachable,
5326 },5408 },
5327 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {5409 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
...@@ -5395,21 +5477,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {...@@ -5395,21 +5477,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
5395 else => unreachable,5477 else => unreachable,
5396 },5478 },
5397 else => unreachable,5479 else => unreachable,
5398 }) orelse {5480 }) orelse return self.fail("TODO implement airSqrt for {}", .{
5399 if (ty.zigTypeTag(mod) != .Float) return self.fail("TODO implement airSqrt for {}", .{5481 ty.fmt(mod),
5400 ty.fmt(mod),5482 });
5401 });
5402
5403 var callee: ["__sqrt?".len]u8 = undefined;
5404 break :result try self.genCall(.{ .lib = .{
5405 .return_type = ty.toIntern(),
5406 .param_types = &.{ty.toIntern()},
5407 .callee = std.fmt.bufPrint(&callee, "{s}sqrt{s}", .{
5408 floatLibcAbiPrefix(ty),
5409 floatLibcAbiSuffix(ty),
5410 }) catch unreachable,
5411 } }, &.{ty}, &.{src_mcv});
5412 };
5413 switch (mir_tag[0]) {5483 switch (mir_tag[0]) {
5414 .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(5484 .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
5415 mir_tag,5485 mir_tag,
...@@ -5536,7 +5606,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn...@@ -5536,7 +5606,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
55365606
5537 const dst_reg = switch (dst_mcv) {5607 const dst_reg = switch (dst_mcv) {
5538 .register => |reg| reg,5608 .register => |reg| reg,
5539 else => try self.register_manager.allocReg(null, gp),5609 else => try self.register_manager.allocReg(null, abi.RegisterClass.gp),
5540 };5610 };
5541 const dst_lock = self.register_manager.lockReg(dst_reg);5611 const dst_lock = self.register_manager.lockReg(dst_reg);
5542 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);5612 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
...@@ -5555,7 +5625,8 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn...@@ -5555,7 +5625,8 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
5555 );5625 );
5556 try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(val_bit_off));5626 try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(val_bit_off));
5557 } else {5627 } else {
5558 const tmp_reg = registerAlias(try self.register_manager.allocReg(null, gp), val_abi_size);5628 const tmp_reg =
5629 registerAlias(try self.register_manager.allocReg(null, abi.RegisterClass.gp), val_abi_size);
5559 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);5630 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
5560 defer self.register_manager.unlockReg(tmp_lock);5631 defer self.register_manager.unlockReg(tmp_lock);
55615632
...@@ -5640,8 +5711,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -5640,8 +5711,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
5640 const ptr_ty = self.typeOf(ty_op.operand);5711 const ptr_ty = self.typeOf(ty_op.operand);
5641 const elem_size = elem_ty.abiSize(mod);5712 const elem_size = elem_ty.abiSize(mod);
56425713
5643 const elem_rc = regClassForType(elem_ty, mod);5714 const elem_rc = self.regClassForType(elem_ty);
5644 const ptr_rc = regClassForType(ptr_ty, mod);5715 const ptr_rc = self.regClassForType(ptr_ty);
56455716
5646 const ptr_mcv = try self.resolveInst(ty_op.operand);5717 const ptr_mcv = try self.resolveInst(ty_op.operand);
5647 const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and5718 const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and
...@@ -5696,13 +5767,13 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In...@@ -5696,13 +5767,13 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
5696 } else if (math.cast(i32, @as(i64, @bitCast(part_mask_not)))) |small| {5767 } else if (math.cast(i32, @as(i64, @bitCast(part_mask_not)))) |small| {
5697 try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, Immediate.s(small));5768 try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, Immediate.s(small));
5698 } else {5769 } else {
5699 const part_mask_reg = try self.register_manager.allocReg(null, gp);5770 const part_mask_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
5700 try self.asmRegisterImmediate(.{ ._, .mov }, part_mask_reg, Immediate.u(part_mask_not));5771 try self.asmRegisterImmediate(.{ ._, .mov }, part_mask_reg, Immediate.u(part_mask_not));
5701 try self.asmMemoryRegister(.{ ._, .@"and" }, limb_mem, part_mask_reg);5772 try self.asmMemoryRegister(.{ ._, .@"and" }, limb_mem, part_mask_reg);
5702 }5773 }
57035774
5704 if (src_bit_size <= 64) {5775 if (src_bit_size <= 64) {
5705 const tmp_reg = try self.register_manager.allocReg(null, gp);5776 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
5706 const tmp_mcv = MCValue{ .register = tmp_reg };5777 const tmp_mcv = MCValue{ .register = tmp_reg };
5707 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);5778 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
5708 defer self.register_manager.unlockReg(tmp_lock);5779 defer self.register_manager.unlockReg(tmp_lock);
...@@ -5840,11 +5911,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -5840,11 +5911,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
5840 const index = extra.field_index;5911 const index = extra.field_index;
58415912
5842 const container_ty = self.typeOf(operand);5913 const container_ty = self.typeOf(operand);
5843 const container_rc = regClassForType(container_ty, mod);5914 const container_rc = self.regClassForType(container_ty);
5844 const field_ty = container_ty.structFieldType(index, mod);5915 const field_ty = container_ty.structFieldType(index, mod);
5845 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;5916 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
5846 const field_rc = regClassForType(field_ty, mod);5917 const field_rc = self.regClassForType(field_ty);
5847 const field_is_gp = field_rc.supersetOf(gp);5918 const field_is_gp = field_rc.supersetOf(abi.RegisterClass.gp);
58485919
5849 const src_mcv = try self.resolveInst(operand);5920 const src_mcv = try self.resolveInst(operand);
5850 const field_off: u32 = switch (container_ty.containerLayout(mod)) {5921 const field_off: u32 = switch (container_ty.containerLayout(mod)) {
...@@ -5868,8 +5939,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -5868,8 +5939,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
5868 @intCast(field_ty.bitSize(mod)),5939 @intCast(field_ty.bitSize(mod)),
5869 );5940 );
58705941
5871 const dst_reg =5942 const dst_reg = try self.register_manager.allocReg(
5872 try self.register_manager.allocReg(if (field_is_gp) inst else null, gp);5943 if (field_is_gp) inst else null,
5944 abi.RegisterClass.gp,
5945 );
5873 const dst_mcv = MCValue{ .register = dst_reg };5946 const dst_mcv = MCValue{ .register = dst_reg };
5874 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);5947 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
5875 defer self.register_manager.unlockReg(dst_lock);5948 defer self.register_manager.unlockReg(dst_lock);
...@@ -5898,7 +5971,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -5898,7 +5971,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
5898 return self.fail("TODO implement struct_field_val with large packed field", .{});5971 return self.fail("TODO implement struct_field_val with large packed field", .{});
5899 }5972 }
59005973
5901 const dst_reg = try self.register_manager.allocReg(if (field_is_gp) inst else null, gp);5974 const dst_reg = try self.register_manager.allocReg(
5975 if (field_is_gp) inst else null,
5976 abi.RegisterClass.gp,
5977 );
5902 const field_extra_bits = self.regExtraBits(field_ty);5978 const field_extra_bits = self.regExtraBits(field_ty);
5903 const load_abi_size =5979 const load_abi_size =
5904 if (field_bit_off < field_extra_bits) field_abi_size else field_abi_size * 2;5980 if (field_bit_off < field_extra_bits) field_abi_size else field_abi_size * 2;
...@@ -5915,7 +5991,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -5915,7 +5991,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
5915 try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(field_bit_off));5991 try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(field_bit_off));
5916 } else {5992 } else {
5917 const tmp_reg = registerAlias(5993 const tmp_reg = registerAlias(
5918 try self.register_manager.allocReg(null, gp),5994 try self.register_manager.allocReg(null, abi.RegisterClass.gp),
5919 field_abi_size,5995 field_abi_size,
5920 );5996 );
5921 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);5997 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
...@@ -5975,7 +6051,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -5975,7 +6051,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
5975 );6051 );
5976 if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg);6052 if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg);
59776053
5978 break :result if (field_rc.supersetOf(gp))6054 break :result if (field_rc.supersetOf(abi.RegisterClass.gp))
5979 dst_mcv6055 dst_mcv
5980 else6056 else
5981 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);6057 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);
...@@ -5996,7 +6072,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -5996,7 +6072,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
5996 self.eflags_inst = inst;6072 self.eflags_inst = inst;
5997 break :result .{ .eflags = ro.eflags };6073 break :result .{ .eflags = ro.eflags };
5998 } else {6074 } else {
5999 const dst_reg = try self.register_manager.allocReg(inst, gp);6075 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
6000 try self.asmSetccRegister(dst_reg.to8(), ro.eflags);6076 try self.asmSetccRegister(dst_reg.to8(), ro.eflags);
6001 break :result .{ .register = dst_reg.to8() };6077 break :result .{ .register = dst_reg.to8() };
6002 },6078 },
...@@ -6117,7 +6193,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC...@@ -6117,7 +6193,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC
6117 .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)),6193 .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)),
6118 .register_pair => unreachable, // unimplemented6194 .register_pair => unreachable, // unimplemented
6119 .memory, .load_got, .load_direct, .load_tlv => {6195 .memory, .load_got, .load_direct, .load_tlv => {
6120 const addr_reg = try self.register_manager.allocReg(null, gp);6196 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6121 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);6197 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
6122 defer self.register_manager.unlockReg(addr_reg_lock);6198 defer self.register_manager.unlockReg(addr_reg_lock);
61236199
...@@ -6219,7 +6295,7 @@ fn genShiftBinOpMir(...@@ -6219,7 +6295,7 @@ fn genShiftBinOpMir(
6219 }),6295 }),
6220 }6296 }
6221 } else if (abi_size <= 16) {6297 } else if (abi_size <= 16) {
6222 const tmp_reg = try self.register_manager.allocReg(null, gp);6298 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6223 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);6299 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6224 defer self.register_manager.unlockReg(tmp_lock);6300 defer self.register_manager.unlockReg(tmp_lock);
62256301
...@@ -6297,11 +6373,11 @@ fn genShiftBinOpMir(...@@ -6297,11 +6373,11 @@ fn genShiftBinOpMir(
6297 }6373 }
6298 },6374 },
6299 else => {6375 else => {
6300 const first_reg = try self.register_manager.allocReg(null, gp);6376 const first_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6301 const first_lock = self.register_manager.lockRegAssumeUnused(first_reg);6377 const first_lock = self.register_manager.lockRegAssumeUnused(first_reg);
6302 defer self.register_manager.unlockReg(first_lock);6378 defer self.register_manager.unlockReg(first_lock);
63036379
6304 const second_reg = try self.register_manager.allocReg(null, gp);6380 const second_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6305 const second_lock = self.register_manager.lockRegAssumeUnused(second_reg);6381 const second_lock = self.register_manager.lockRegAssumeUnused(second_reg);
6306 defer self.register_manager.unlockReg(second_lock);6382 defer self.register_manager.unlockReg(second_lock);
63076383
...@@ -6663,7 +6739,7 @@ fn genBinOp(...@@ -6663,7 +6739,7 @@ fn genBinOp(
6663 if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: {6739 if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: {
6664 try self.register_manager.getReg(.xmm0, null);6740 try self.register_manager.getReg(.xmm0, null);
6665 break :mask .xmm0;6741 break :mask .xmm0;
6666 } else try self.register_manager.allocReg(null, sse),6742 } else try self.register_manager.allocReg(null, abi.RegisterClass.sse),
6667 abi_size,6743 abi_size,
6668 ) else null,6744 ) else null,
6669 .rem, .mod => return self.fail("TODO implement genBinOp for {s} {}", .{6745 .rem, .mod => return self.fail("TODO implement genBinOp for {s} {}", .{
...@@ -6916,7 +6992,8 @@ fn genBinOp(...@@ -6916,7 +6992,8 @@ fn genBinOp(
6916 .Float => switch (lhs_ty.floatBits(self.target.*)) {6992 .Float => switch (lhs_ty.floatBits(self.target.*)) {
6917 16 => {6993 16 => {
6918 assert(self.hasFeature(.f16c));6994 assert(self.hasFeature(.f16c));
6919 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();6995 const tmp_reg =
6996 (try self.register_manager.allocReg(null, abi.RegisterClass.sse)).to128();
6920 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);6997 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6921 defer self.register_manager.unlockReg(tmp_lock);6998 defer self.register_manager.unlockReg(tmp_lock);
69226999
...@@ -7223,7 +7300,10 @@ fn genBinOp(...@@ -7223,7 +7300,10 @@ fn genBinOp(
7223 assert(self.hasFeature(.f16c));7300 assert(self.hasFeature(.f16c));
7224 switch (lhs_ty.vectorLen(mod)) {7301 switch (lhs_ty.vectorLen(mod)) {
7225 1 => {7302 1 => {
7226 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();7303 const tmp_reg = (try self.register_manager.allocReg(
7304 null,
7305 abi.RegisterClass.sse,
7306 )).to128();
7227 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7307 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7228 defer self.register_manager.unlockReg(tmp_lock);7308 defer self.register_manager.unlockReg(tmp_lock);
72297309
...@@ -7267,7 +7347,10 @@ fn genBinOp(...@@ -7267,7 +7347,10 @@ fn genBinOp(
7267 return dst_mcv;7347 return dst_mcv;
7268 },7348 },
7269 2 => {7349 2 => {
7270 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();7350 const tmp_reg = (try self.register_manager.allocReg(
7351 null,
7352 abi.RegisterClass.sse,
7353 )).to128();
7271 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7354 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7272 defer self.register_manager.unlockReg(tmp_lock);7355 defer self.register_manager.unlockReg(tmp_lock);
72737356
...@@ -7315,7 +7398,10 @@ fn genBinOp(...@@ -7315,7 +7398,10 @@ fn genBinOp(
7315 return dst_mcv;7398 return dst_mcv;
7316 },7399 },
7317 3...4 => {7400 3...4 => {
7318 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();7401 const tmp_reg = (try self.register_manager.allocReg(
7402 null,
7403 abi.RegisterClass.sse,
7404 )).to128();
7319 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7405 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7320 defer self.register_manager.unlockReg(tmp_lock);7406 defer self.register_manager.unlockReg(tmp_lock);
73217407
...@@ -7355,7 +7441,10 @@ fn genBinOp(...@@ -7355,7 +7441,10 @@ fn genBinOp(
7355 return dst_mcv;7441 return dst_mcv;
7356 },7442 },
7357 5...8 => {7443 5...8 => {
7358 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to256();7444 const tmp_reg = (try self.register_manager.allocReg(
7445 null,
7446 abi.RegisterClass.sse,
7447 )).to256();
7359 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7448 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7360 defer self.register_manager.unlockReg(tmp_lock);7449 defer self.register_manager.unlockReg(tmp_lock);
73617450
...@@ -7948,7 +8037,8 @@ fn genBinOpMir(...@@ -7948,7 +8037,8 @@ fn genBinOpMir(
7948 const dst_info: OpInfo = switch (dst_mcv) {8037 const dst_info: OpInfo = switch (dst_mcv) {
7949 else => unreachable,8038 else => unreachable,
7950 .memory, .load_got, .load_direct, .load_tlv => dst: {8039 .memory, .load_got, .load_direct, .load_tlv => dst: {
7951 const dst_addr_reg = (try self.register_manager.allocReg(null, gp)).to64();8040 const dst_addr_reg =
8041 (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
7952 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);8042 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
7953 errdefer self.register_manager.unlockReg(dst_addr_lock);8043 errdefer self.register_manager.unlockReg(dst_addr_lock);
79548044
...@@ -7993,7 +8083,8 @@ fn genBinOpMir(...@@ -7993,7 +8083,8 @@ fn genBinOpMir(
7993 else => unreachable,8083 else => unreachable,
7994 }8084 }
79958085
7996 const src_addr_reg = (try self.register_manager.allocReg(null, gp)).to64();8086 const src_addr_reg =
8087 (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
7997 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);8088 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
7998 errdefer self.register_manager.unlockReg(src_addr_lock);8089 errdefer self.register_manager.unlockReg(src_addr_lock);
79998090
...@@ -8619,6 +8710,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -8619,6 +8710,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
8619 const mod = self.bin_file.options.module.?;8710 const mod = self.bin_file.options.module.?;
8620 const un_op = self.air.instructions.items(.data)[inst].un_op;8711 const un_op = self.air.instructions.items(.data)[inst].un_op;
8621 const operand = try self.resolveInst(un_op);8712 const operand = try self.resolveInst(un_op);
8713
8622 const ret_ty = self.fn_type.fnReturnType(mod);8714 const ret_ty = self.fn_type.fnReturnType(mod);
8623 switch (self.ret_mcv.short) {8715 switch (self.ret_mcv.short) {
8624 .none => {},8716 .none => {},
...@@ -8633,6 +8725,8 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -8633,6 +8725,8 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
8633 },8725 },
8634 else => unreachable,8726 else => unreachable,
8635 }8727 }
8728 self.ret_mcv.liveOut(self, inst);
8729
8636 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction8730 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction
8637 // which is available if the jump is 127 bytes or less forward.8731 // which is available if the jump is 127 bytes or less forward.
8638 const jmp_reloc = try self.asmJmpReloc(undefined);8732 const jmp_reloc = try self.asmJmpReloc(undefined);
...@@ -8643,6 +8737,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -8643,6 +8737,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
8643fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {8737fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
8644 const un_op = self.air.instructions.items(.data)[inst].un_op;8738 const un_op = self.air.instructions.items(.data)[inst].un_op;
8645 const ptr = try self.resolveInst(un_op);8739 const ptr = try self.resolveInst(un_op);
8740
8646 const ptr_ty = self.typeOf(un_op);8741 const ptr_ty = self.typeOf(un_op);
8647 switch (self.ret_mcv.short) {8742 switch (self.ret_mcv.short) {
8648 .none => {},8743 .none => {},
...@@ -8650,6 +8745,8 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -8650,6 +8745,8 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
8650 .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr),8745 .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr),
8651 else => unreachable,8746 else => unreachable,
8652 }8747 }
8748 self.ret_mcv.liveOut(self, inst);
8749
8653 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction8750 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction
8654 // which is available if the jump is 127 bytes or less forward.8751 // which is available if the jump is 127 bytes or less forward.
8655 const jmp_reloc = try self.asmJmpReloc(undefined);8752 const jmp_reloc = try self.asmJmpReloc(undefined);
...@@ -8800,8 +8897,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8800,8 +8897,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8800 else => unreachable,8897 else => unreachable,
8801 }8898 }
88028899
8803 const dst_addr_reg =8900 const dst_addr_reg = (try self.register_manager.allocReg(
8804 (try self.register_manager.allocReg(null, gp)).to64();8901 null,
8902 abi.RegisterClass.gp,
8903 )).to64();
8805 const dst_addr_lock =8904 const dst_addr_lock =
8806 self.register_manager.lockRegAssumeUnused(dst_addr_reg);8905 self.register_manager.lockRegAssumeUnused(dst_addr_reg);
8807 errdefer self.register_manager.unlockReg(dst_addr_lock);8906 errdefer self.register_manager.unlockReg(dst_addr_lock);
...@@ -8856,8 +8955,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8856,8 +8955,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8856 else => unreachable,8955 else => unreachable,
8857 }8956 }
88588957
8859 const src_addr_reg =8958 const src_addr_reg = (try self.register_manager.allocReg(
8860 (try self.register_manager.allocReg(null, gp)).to64();8959 null,
8960 abi.RegisterClass.gp,
8961 )).to64();
8861 const src_addr_lock =8962 const src_addr_lock =
8862 self.register_manager.lockRegAssumeUnused(src_addr_reg);8963 self.register_manager.lockRegAssumeUnused(src_addr_reg);
8863 errdefer self.register_manager.unlockReg(src_addr_lock);8964 errdefer self.register_manager.unlockReg(src_addr_lock);
...@@ -8876,8 +8977,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8876,8 +8977,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8876 defer if (src_info) |info|8977 defer if (src_info) |info|
8877 self.register_manager.unlockReg(info.addr_lock);8978 self.register_manager.unlockReg(info.addr_lock);
88788979
8879 const regs =8980 const regs = try self.register_manager.allocRegs(
8880 try self.register_manager.allocRegs(2, .{ null, null }, gp);8981 2,
8982 .{ null, null },
8983 abi.RegisterClass.gp,
8984 );
8881 const acc_reg = regs[0].to64();8985 const acc_reg = regs[0].to64();
8882 const locks = self.register_manager.lockRegsAssumeUnused(2, regs);8986 const locks = self.register_manager.lockRegsAssumeUnused(2, regs);
8883 defer for (locks) |lock| self.register_manager.unlockReg(lock);8987 defer for (locks) |lock| self.register_manager.unlockReg(lock);
...@@ -8964,12 +9068,14 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8964,12 +9068,14 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8964 switch (ty.floatBits(self.target.*)) {9068 switch (ty.floatBits(self.target.*)) {
8965 16 => {9069 16 => {
8966 assert(self.hasFeature(.f16c));9070 assert(self.hasFeature(.f16c));
8967 const tmp1_reg = (try self.register_manager.allocReg(null, sse)).to128();9071 const tmp1_reg =
9072 (try self.register_manager.allocReg(null, abi.RegisterClass.sse)).to128();
8968 const tmp1_mcv = MCValue{ .register = tmp1_reg };9073 const tmp1_mcv = MCValue{ .register = tmp1_reg };
8969 const tmp1_lock = self.register_manager.lockRegAssumeUnused(tmp1_reg);9074 const tmp1_lock = self.register_manager.lockRegAssumeUnused(tmp1_reg);
8970 defer self.register_manager.unlockReg(tmp1_lock);9075 defer self.register_manager.unlockReg(tmp1_lock);
89719076
8972 const tmp2_reg = (try self.register_manager.allocReg(null, sse)).to128();9077 const tmp2_reg =
9078 (try self.register_manager.allocReg(null, abi.RegisterClass.sse)).to128();
8973 const tmp2_mcv = MCValue{ .register = tmp2_reg };9079 const tmp2_mcv = MCValue{ .register = tmp2_reg };
8974 const tmp2_lock = self.register_manager.lockRegAssumeUnused(tmp2_reg);9080 const tmp2_lock = self.register_manager.lockRegAssumeUnused(tmp2_reg);
8975 defer self.register_manager.unlockReg(tmp2_lock);9081 defer self.register_manager.unlockReg(tmp2_lock);
...@@ -9032,7 +9138,7 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -9032,7 +9138,7 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
9032 const mod = self.bin_file.options.module.?;9138 const mod = self.bin_file.options.module.?;
9033 const un_op = self.air.instructions.items(.data)[inst].un_op;9139 const un_op = self.air.instructions.items(.data)[inst].un_op;
90349140
9035 const addr_reg = try self.register_manager.allocReg(null, gp);9141 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
9036 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);9142 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
9037 defer self.register_manager.unlockReg(addr_lock);9143 defer self.register_manager.unlockReg(addr_lock);
9038 try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod));9144 try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod));
...@@ -9293,7 +9399,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -9293,7 +9399,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
9293 .load_direct,9399 .load_direct,
9294 .load_tlv,9400 .load_tlv,
9295 => {9401 => {
9296 const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();9402 const addr_reg = (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
9297 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);9403 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
9298 defer self.register_manager.unlockReg(addr_reg_lock);9404 defer self.register_manager.unlockReg(addr_reg_lock);
92999405
...@@ -9778,7 +9884,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9778,7 +9884,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9778 else => self.typeOf(output).childType(mod),9884 else => self.typeOf(output).childType(mod),
9779 };9885 };
9780 const arg_maybe_reg: ?Register = if (mem.eql(u8, constraint, "=r"))9886 const arg_maybe_reg: ?Register = if (mem.eql(u8, constraint, "=r"))
9781 self.register_manager.tryAllocReg(maybe_inst, regClassForType(ty, mod)) orelse9887 self.register_manager.tryAllocReg(maybe_inst, self.regClassForType(ty)) orelse
9782 return self.fail("ran out of registers lowering inline asm", .{})9888 return self.fail("ran out of registers lowering inline asm", .{})
9783 else if (mem.eql(u8, constraint, "=m"))9889 else if (mem.eql(u8, constraint, "=m"))
9784 if (output != .none) null else return self.fail(9890 if (output != .none) null else return self.fail(
...@@ -9786,7 +9892,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9786,7 +9892,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9786 .{},9892 .{},
9787 )9893 )
9788 else if (mem.eql(u8, constraint, "=g"))9894 else if (mem.eql(u8, constraint, "=g"))
9789 self.register_manager.tryAllocReg(maybe_inst, regClassForType(ty, mod)) orelse9895 self.register_manager.tryAllocReg(maybe_inst, self.regClassForType(ty)) orelse
9790 if (output != .none) null else return self.fail(9896 if (output != .none) null else return self.fail(
9791 "ran out of register lowering inline asm",9897 "ran out of register lowering inline asm",
9792 .{},9898 .{},
...@@ -9840,7 +9946,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9840,7 +9946,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9840 break :arg temp_mcv;9946 break :arg temp_mcv;
9841 },9947 },
9842 }9948 }
9843 const addr_reg = self.register_manager.tryAllocReg(null, gp) orelse {9949 const addr_reg = self.register_manager.tryAllocReg(null, abi.RegisterClass.gp) orelse {
9844 const temp_mcv = try self.allocTempRegOrMem(ty, false);9950 const temp_mcv = try self.allocTempRegOrMem(ty, false);
9845 try self.genCopy(ty, temp_mcv, input_mcv);9951 try self.genCopy(ty, temp_mcv, input_mcv);
9846 break :arg temp_mcv;9952 break :arg temp_mcv;
...@@ -10946,8 +11052,8 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -10946,8 +11052,8 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
10946 const src_ty = self.typeOf(ty_op.operand);11052 const src_ty = self.typeOf(ty_op.operand);
1094711053
10948 const result = result: {11054 const result = result: {
10949 const dst_rc = regClassForType(dst_ty, mod);11055 const dst_rc = self.regClassForType(dst_ty);
10950 const src_rc = regClassForType(src_ty, mod);11056 const src_rc = self.regClassForType(src_ty);
10951 const src_mcv = try self.resolveInst(ty_op.operand);11057 const src_mcv = try self.resolveInst(ty_op.operand);
1095211058
10953 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;11059 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
...@@ -11074,7 +11180,7 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void {...@@ -11074,7 +11180,7 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void {
1107411180
11075 if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg);11181 if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg);
1107611182
11077 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod));11183 const dst_reg = try self.register_manager.allocReg(inst, self.regClassForType(dst_ty));
11078 const dst_mcv = MCValue{ .register = dst_reg };11184 const dst_mcv = MCValue{ .register = dst_reg };
11079 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);11185 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
11080 defer self.register_manager.unlockReg(dst_lock);11186 defer self.register_manager.unlockReg(dst_lock);
...@@ -11151,7 +11257,7 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void {...@@ -11151,7 +11257,7 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void {
11151 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);11257 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
11152 defer self.register_manager.unlockReg(src_lock);11258 defer self.register_manager.unlockReg(src_lock);
1115311259
11154 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod));11260 const dst_reg = try self.register_manager.allocReg(inst, self.regClassForType(dst_ty));
11155 const dst_mcv = MCValue{ .register = dst_reg };11261 const dst_mcv = MCValue{ .register = dst_reg };
11156 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);11262 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
11157 defer self.register_manager.unlockReg(dst_lock);11263 defer self.register_manager.unlockReg(dst_lock);
...@@ -11332,7 +11438,7 @@ fn atomicOp(...@@ -11332,7 +11438,7 @@ fn atomicOp(
11332 .SeqCst => .xchg,11438 .SeqCst => .xchg,
11333 };11439 };
1133411440
11335 const dst_reg = try self.register_manager.allocReg(null, gp);11441 const dst_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
11336 const dst_mcv = MCValue{ .register = dst_reg };11442 const dst_mcv = MCValue{ .register = dst_reg };
11337 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);11443 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
11338 defer self.register_manager.unlockReg(dst_lock);11444 defer self.register_manager.unlockReg(dst_lock);
...@@ -11354,7 +11460,7 @@ fn atomicOp(...@@ -11354,7 +11460,7 @@ fn atomicOp(
11354 return if (unused) .unreach else dst_mcv;11460 return if (unused) .unreach else dst_mcv;
11355 },11461 },
11356 .loop => _ = if (val_abi_size <= 8) {11462 .loop => _ = if (val_abi_size <= 8) {
11357 const tmp_reg = try self.register_manager.allocReg(null, gp);11463 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
11358 const tmp_mcv = MCValue{ .register = tmp_reg };11464 const tmp_mcv = MCValue{ .register = tmp_reg };
11359 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);11465 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
11360 defer self.register_manager.unlockReg(tmp_lock);11466 defer self.register_manager.unlockReg(tmp_lock);
...@@ -11628,7 +11734,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -11628,7 +11734,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1162811734
11629 // Used to store the number of elements for comparison.11735 // Used to store the number of elements for comparison.
11630 // After comparison, updated to store number of bytes needed to copy.11736 // After comparison, updated to store number of bytes needed to copy.
11631 const len_reg = try self.register_manager.allocReg(null, gp);11737 const len_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
11632 const len_mcv: MCValue = .{ .register = len_reg };11738 const len_mcv: MCValue = .{ .register = len_reg };
11633 const len_lock = self.register_manager.lockRegAssumeUnused(len_reg);11739 const len_lock = self.register_manager.lockRegAssumeUnused(len_reg);
11634 defer self.register_manager.unlockReg(len_lock);11740 defer self.register_manager.unlockReg(len_lock);
...@@ -11638,7 +11744,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -11638,7 +11744,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
11638 const skip_reloc = try self.asmJccReloc(undefined, .z);11744 const skip_reloc = try self.asmJccReloc(undefined, .z);
11639 try self.store(slice_ptr_ty, ptr, src_val);11745 try self.store(slice_ptr_ty, ptr, src_val);
1164011746
11641 const second_elem_ptr_reg = try self.register_manager.allocReg(null, gp);11747 const second_elem_ptr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
11642 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };11748 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };
11643 const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg);11749 const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg);
11644 defer self.register_manager.unlockReg(second_elem_ptr_lock);11750 defer self.register_manager.unlockReg(second_elem_ptr_lock);
...@@ -11667,7 +11773,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -11667,7 +11773,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
11667 assert(len != 0); // prevented by Sema11773 assert(len != 0); // prevented by Sema
11668 try self.store(elem_ptr_ty, dst_ptr, src_val);11774 try self.store(elem_ptr_ty, dst_ptr, src_val);
1166911775
11670 const second_elem_ptr_reg = try self.register_manager.allocReg(null, gp);11776 const second_elem_ptr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
11671 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };11777 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };
11672 const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg);11778 const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg);
11673 defer self.register_manager.unlockReg(second_elem_ptr_lock);11779 defer self.register_manager.unlockReg(second_elem_ptr_lock);
...@@ -11774,16 +11880,16 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {...@@ -11774,16 +11880,16 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
11774 const err_lock = self.register_manager.lockRegAssumeUnused(err_reg);11880 const err_lock = self.register_manager.lockRegAssumeUnused(err_reg);
11775 defer self.register_manager.unlockReg(err_lock);11881 defer self.register_manager.unlockReg(err_lock);
1177611882
11777 const addr_reg = try self.register_manager.allocReg(null, gp);11883 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
11778 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);11884 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
11779 defer self.register_manager.unlockReg(addr_lock);11885 defer self.register_manager.unlockReg(addr_lock);
11780 try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod));11886 try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod));
1178111887
11782 const start_reg = try self.register_manager.allocReg(null, gp);11888 const start_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
11783 const start_lock = self.register_manager.lockRegAssumeUnused(start_reg);11889 const start_lock = self.register_manager.lockRegAssumeUnused(start_reg);
11784 defer self.register_manager.unlockReg(start_lock);11890 defer self.register_manager.unlockReg(start_lock);
1178511891
11786 const end_reg = try self.register_manager.allocReg(null, gp);11892 const end_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
11787 const end_lock = self.register_manager.lockRegAssumeUnused(end_reg);11893 const end_lock = self.register_manager.lockRegAssumeUnused(end_reg);
11788 defer self.register_manager.unlockReg(end_lock);11894 defer self.register_manager.unlockReg(end_lock);
1178911895
...@@ -11851,7 +11957,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {...@@ -11851,7 +11957,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
11851 const mod = self.bin_file.options.module.?;11957 const mod = self.bin_file.options.module.?;
11852 const ty_op = self.air.instructions.items(.data)[inst].ty_op;11958 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
11853 const vector_ty = self.typeOfIndex(inst);11959 const vector_ty = self.typeOfIndex(inst);
11854 const dst_rc = regClassForType(vector_ty, mod);11960 const dst_rc = self.regClassForType(vector_ty);
11855 const scalar_ty = vector_ty.scalarType(mod);11961 const scalar_ty = vector_ty.scalarType(mod);
1185611962
11857 const src_mcv = try self.resolveInst(ty_op.operand);11963 const src_mcv = try self.resolveInst(ty_op.operand);
src/arch/x86_64/Encoding.zig+1-1
...@@ -260,7 +260,7 @@ pub const Mnemonic = enum {...@@ -260,7 +260,7 @@ pub const Mnemonic = enum {
260 ud2,260 ud2,
261 xadd, xchg, xor,261 xadd, xchg, xor,
262 // X87262 // X87
263 ffree, fisttp, fld, fst, fstp,263 fabs, fchs, ffree, fisttp, fld, fst, fstp,
264 // MMX264 // MMX
265 movd, movq,265 movd, movq,
266 packssdw, packsswb, packuswb,266 packssdw, packsswb, packuswb,
src/arch/x86_64/Mir.zig+4
...@@ -442,6 +442,10 @@ pub const Inst = struct {...@@ -442,6 +442,10 @@ pub const Inst = struct {
442 /// Bitwise logical xor of packed double-precision floating-point values442 /// Bitwise logical xor of packed double-precision floating-point values
443 xor,443 xor,
444444
445 /// Absolute value
446 abs,
447 /// Change sign
448 chs,
445 /// Free floating-point register449 /// Free floating-point register
446 free,450 free,
447 /// Store integer with truncation451 /// Store integer with truncation
src/arch/x86_64/encodings.zig+4
...@@ -829,6 +829,10 @@ pub const table = [_]Entry{...@@ -829,6 +829,10 @@ pub const table = [_]Entry{
829 .{ .xor, .rm, &.{ .r64, .rm64 }, &.{ 0x33 }, 0, .long, .none },829 .{ .xor, .rm, &.{ .r64, .rm64 }, &.{ 0x33 }, 0, .long, .none },
830830
831 // X87831 // X87
832 .{ .fabs, .np, &.{}, &.{ 0xd9, 0xe1 }, 0, .none, .x87 },
833
834 .{ .fchs, .np, &.{}, &.{ 0xd9, 0xe0 }, 0, .none, .x87 },
835
832 .{ .ffree, .o, &.{ .st }, &.{ 0xdd, 0xc0 }, 0, .none, .x87 },836 .{ .ffree, .o, &.{ .st }, &.{ 0xdd, 0xc0 }, 0, .none, .x87 },
833837
834 .{ .fisttp, .m, &.{ .m16 }, &.{ 0xdf }, 1, .none, .x87 },838 .{ .fisttp, .m, &.{ .m16 }, &.{ 0xdf }, 1, .none, .x87 },
src/register_manager.zig+4-2
...@@ -91,11 +91,13 @@ pub fn RegisterManager(...@@ -91,11 +91,13 @@ pub fn RegisterManager(
91 return null;91 return null;
92 }92 }
9393
94 pub fn indexOfRegIntoTracked(reg: Register) ?RegisterBitSet.ShiftInt {94 pub fn indexOfRegIntoTracked(
95 reg: Register,
96 ) ?std.math.IntFittingRange(0, tracked_registers.len) {
95 return indexOfReg(tracked_registers, reg);97 return indexOfReg(tracked_registers, reg);
96 }98 }
9799
98 pub fn regAtTrackedIndex(index: RegisterBitSet.ShiftInt) Register {100 pub fn regAtTrackedIndex(index: std.math.IntFittingRange(0, tracked_registers.len)) Register {
99 return tracked_registers[index];101 return tracked_registers[index];
100 }102 }
101103
test/behavior/abs.zig+1-1
...@@ -95,7 +95,7 @@ test "@abs floats" {...@@ -95,7 +95,7 @@ test "@abs floats" {
95 try comptime testAbsFloats(f64);95 try comptime testAbsFloats(f64);
96 try testAbsFloats(f64);96 try testAbsFloats(f64);
97 try comptime testAbsFloats(f80);97 try comptime testAbsFloats(f80);
98 if (builtin.zig_backend != .stage2_x86_64 and builtin.zig_backend != .stage2_wasm) try testAbsFloats(f80);98 if (builtin.zig_backend != .stage2_wasm) try testAbsFloats(f80);
99 try comptime testAbsFloats(f128);99 try comptime testAbsFloats(f128);
100 if (builtin.zig_backend != .stage2_wasm) try testAbsFloats(f128);100 if (builtin.zig_backend != .stage2_wasm) try testAbsFloats(f128);
101}101}
test/behavior/floatop.zig+10-10
...@@ -270,7 +270,7 @@ test "@sqrt f80/f128/c_longdouble" {...@@ -270,7 +270,7 @@ test "@sqrt f80/f128/c_longdouble" {
270 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO270 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
271 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO271 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
272 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;272 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
273 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;273 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
274274
275 if (builtin.os.tag == .freebsd) {275 if (builtin.os.tag == .freebsd) {
276 // TODO https://github.com/ziglang/zig/issues/10875276 // TODO https://github.com/ziglang/zig/issues/10875
...@@ -378,7 +378,7 @@ test "@sin f80/f128/c_longdouble" {...@@ -378,7 +378,7 @@ test "@sin f80/f128/c_longdouble" {
378 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO378 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
379 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO379 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
380 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;380 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
381 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;381 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
382382
383 try testSin(f80);383 try testSin(f80);
384 comptime try testSin(f80);384 comptime try testSin(f80);
...@@ -447,7 +447,7 @@ test "@cos f80/f128/c_longdouble" {...@@ -447,7 +447,7 @@ test "@cos f80/f128/c_longdouble" {
447 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO447 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
448 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO448 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
449 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;449 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
450 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;450 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
451451
452 try testCos(f80);452 try testCos(f80);
453 try comptime testCos(f80);453 try comptime testCos(f80);
...@@ -516,7 +516,7 @@ test "@tan f80/f128/c_longdouble" {...@@ -516,7 +516,7 @@ test "@tan f80/f128/c_longdouble" {
516 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO516 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
517 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO517 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
518 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;518 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
519 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;519 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
520520
521 try testTan(f80);521 try testTan(f80);
522 try comptime testTan(f80);522 try comptime testTan(f80);
...@@ -585,7 +585,7 @@ test "@exp f80/f128/c_longdouble" {...@@ -585,7 +585,7 @@ test "@exp f80/f128/c_longdouble" {
585 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO585 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
586 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO586 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
587 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;587 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
588 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;588 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
589589
590 try testExp(f80);590 try testExp(f80);
591 try comptime testExp(f80);591 try comptime testExp(f80);
...@@ -654,7 +654,7 @@ test "@exp2 f80/f128/c_longdouble" {...@@ -654,7 +654,7 @@ test "@exp2 f80/f128/c_longdouble" {
654 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO654 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
655 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO655 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
656 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;656 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
657 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;657 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
658658
659 try testExp2(f80);659 try testExp2(f80);
660 try comptime testExp2(f80);660 try comptime testExp2(f80);
...@@ -723,7 +723,7 @@ test "@log f80/f128/c_longdouble" {...@@ -723,7 +723,7 @@ test "@log f80/f128/c_longdouble" {
723 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO723 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
724 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO724 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
725 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;725 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
726 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;726 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
727727
728 try testLog(f80);728 try testLog(f80);
729 try comptime testLog(f80);729 try comptime testLog(f80);
...@@ -790,7 +790,7 @@ test "@log2 f80/f128/c_longdouble" {...@@ -790,7 +790,7 @@ test "@log2 f80/f128/c_longdouble" {
790 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO790 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
791 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO791 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
792 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;792 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
793 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;793 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
794794
795 try testLog2(f80);795 try testLog2(f80);
796 try comptime testLog2(f80);796 try comptime testLog2(f80);
...@@ -863,7 +863,7 @@ test "@log10 f80/f128/c_longdouble" {...@@ -863,7 +863,7 @@ test "@log10 f80/f128/c_longdouble" {
863 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO863 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
864 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO864 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
865 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;865 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
866 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;866 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
867867
868 try testLog10(f80);868 try testLog10(f80);
869 try comptime testLog10(f80);869 try comptime testLog10(f80);
...@@ -929,7 +929,7 @@ test "@abs f80/f128/c_longdouble" {...@@ -929,7 +929,7 @@ test "@abs f80/f128/c_longdouble" {
929 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO929 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
930 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;930 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
931 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO931 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
932 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;932 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
933933
934 try testFabs(f80);934 try testFabs(f80);
935 try comptime testFabs(f80);935 try comptime testFabs(f80);