| ... | @@ -2856,10 +2856,14 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2856,10 +2856,14 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2856 | .immediate => |imm| { | 2856 | .immediate => |imm| { |
| 2857 | switch (abi_size) { | 2857 | switch (abi_size) { |
| 2858 | 1, 2, 4 => { | 2858 | 1, 2, 4 => { |
| | 2859 | const immediate = if (value_ty.isSignedInt()) |
| | 2860 | Immediate.s(@intCast(i32, @bitCast(i64, imm))) |
| | 2861 | else |
| | 2862 | Immediate.u(@truncate(u32, imm)); |
| 2859 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ | 2863 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 2860 | .base = reg.to64(), | 2864 | .base = reg.to64(), |
| 2861 | .disp = 0, | 2865 | .disp = 0, |
| 2862 | }), Immediate.u(@truncate(u32, imm))); | 2866 | }), immediate); |
| 2863 | }, | 2867 | }, |
| 2864 | 8 => { | 2868 | 8 => { |
| 2865 | // TODO: optimization: if the imm is only using the lower | 2869 | // TODO: optimization: if the imm is only using the lower |
| ... | @@ -3580,7 +3584,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3580,7 +3584,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3580 | const actual_tag: Mir.Inst.Tag = switch (dst_ty.tag()) { | 3584 | const actual_tag: Mir.Inst.Tag = switch (dst_ty.tag()) { |
| 3581 | .f32 => switch (mir_tag) { | 3585 | .f32 => switch (mir_tag) { |
| 3582 | .add => .addss, | 3586 | .add => .addss, |
| 3583 | .cmp => .cmpss, | 3587 | .cmp => .ucomiss, |
| 3584 | else => return self.fail( | 3588 | else => return self.fail( |
| 3585 | "TODO genBinOpMir for f32 register-register with MIR tag {}", | 3589 | "TODO genBinOpMir for f32 register-register with MIR tag {}", |
| 3586 | .{mir_tag}, | 3590 | .{mir_tag}, |
| ... | @@ -3588,7 +3592,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3588,7 +3592,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3588 | }, | 3592 | }, |
| 3589 | .f64 => switch (mir_tag) { | 3593 | .f64 => switch (mir_tag) { |
| 3590 | .add => .addsd, | 3594 | .add => .addsd, |
| 3591 | .cmp => .cmpsd, | 3595 | .cmp => .ucomisd, |
| 3592 | else => return self.fail( | 3596 | else => return self.fail( |
| 3593 | "TODO genBinOpMir for f64 register-register with MIR tag {}", | 3597 | "TODO genBinOpMir for f64 register-register with MIR tag {}", |
| 3594 | .{mir_tag}, | 3598 | .{mir_tag}, |
| ... | @@ -3599,7 +3603,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3599,7 +3603,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3599 | .{dst_ty.fmtDebug()}, | 3603 | .{dst_ty.fmtDebug()}, |
| 3600 | ), | 3604 | ), |
| 3601 | }; | 3605 | }; |
| 3602 | try self.asmRegisterRegister(actual_tag, dst_reg.to128(), src_reg.to128()); | 3606 | return self.asmRegisterRegister(actual_tag, dst_reg.to128(), src_reg.to128()); |
| 3603 | } | 3607 | } |
| 3604 | | 3608 | |
| 3605 | return self.fail("TODO genBinOpMir for float register-register and no intrinsics", .{}); | 3609 | return self.fail("TODO genBinOpMir for float register-register and no intrinsics", .{}); |
| ... | @@ -5255,11 +5259,14 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE | ... | @@ -5255,11 +5259,14 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5255 | // TODO | 5259 | // TODO |
| 5256 | // We have a positive stack offset value but we want a twos complement negative | 5260 | // We have a positive stack offset value but we want a twos complement negative |
| 5257 | // offset from rbp, which is at the top of the stack frame. | 5261 | // offset from rbp, which is at the top of the stack frame. |
| 5258 | // mov [rbp+offset], immediate | 5262 | const immediate = if (ty.isSignedInt()) |
| | 5263 | Immediate.s(@intCast(i32, @bitCast(i64, imm))) |
| | 5264 | else |
| | 5265 | Immediate.u(@intCast(u32, imm)); |
| 5259 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ | 5266 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5260 | .base = .rsp, | 5267 | .base = .rsp, |
| 5261 | .disp = -stack_offset, | 5268 | .disp = -stack_offset, |
| 5262 | }), Immediate.u(@intCast(u32, imm))); | 5269 | }), immediate); |
| 5263 | }, | 5270 | }, |
| 5264 | 8 => { | 5271 | 8 => { |
| 5265 | const reg = try self.copyToTmpRegister(ty, mcv); | 5272 | const reg = try self.copyToTmpRegister(ty, mcv); |
| ... | @@ -5340,10 +5347,19 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -5340,10 +5347,19 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5340 | if (!self.wantSafety()) | 5347 | if (!self.wantSafety()) |
| 5341 | return; // The already existing value will do just fine. | 5348 | return; // The already existing value will do just fine. |
| 5342 | // TODO Upgrade this to a memset call when we have that available. | 5349 | // TODO Upgrade this to a memset call when we have that available. |
| 5343 | switch (ty.abiSize(self.target.*)) { | 5350 | switch (abi_size) { |
| 5344 | 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }, opts), | 5351 | 1, 2, 4 => { |
| 5345 | 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }, opts), | 5352 | const value: u64 = switch (abi_size) { |
| 5346 | 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }, opts), | 5353 | 1 => 0xaa, |
| | 5354 | 2 => 0xaaaa, |
| | 5355 | 4 => 0xaaaaaaaa, |
| | 5356 | else => unreachable, |
| | 5357 | }; |
| | 5358 | return self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| | 5359 | .base = opts.dest_stack_base orelse .rbp, |
| | 5360 | .disp = -stack_offset, |
| | 5361 | }), Immediate.u(value)); |
| | 5362 | }, |
| 5347 | 8 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa }, opts), | 5363 | 8 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa }, opts), |
| 5348 | else => |x| return self.genInlineMemset( | 5364 | else => |x| return self.genInlineMemset( |
| 5349 | .{ .stack_offset = stack_offset }, | 5365 | .{ .stack_offset = stack_offset }, |
| ... | @@ -5385,13 +5401,17 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -5385,13 +5401,17 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5385 | try self.asmMemoryImmediate(.mov, Memory.sib(.byte, .{ | 5401 | try self.asmMemoryImmediate(.mov, Memory.sib(.byte, .{ |
| 5386 | .base = base_reg, | 5402 | .base = base_reg, |
| 5387 | .disp = -stack_offset, | 5403 | .disp = -stack_offset, |
| 5388 | }), Immediate.u(@truncate(u32, x_big))); | 5404 | }), Immediate.u(@truncate(u8, x_big))); |
| 5389 | }, | 5405 | }, |
| 5390 | 1, 2, 4 => { | 5406 | 1, 2, 4 => { |
| | 5407 | const immediate = if (ty.isSignedInt()) |
| | 5408 | Immediate.s(@truncate(i32, @bitCast(i64, x_big))) |
| | 5409 | else |
| | 5410 | Immediate.u(@intCast(u32, x_big)); |
| 5391 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ | 5411 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5392 | .base = base_reg, | 5412 | .base = base_reg, |
| 5393 | .disp = -stack_offset, | 5413 | .disp = -stack_offset, |
| 5394 | }), Immediate.u(@truncate(u32, x_big))); | 5414 | }), immediate); |
| 5395 | }, | 5415 | }, |
| 5396 | 8 => { | 5416 | 8 => { |
| 5397 | // 64 bit write to memory would take two mov's anyways so we | 5417 | // 64 bit write to memory would take two mov's anyways so we |
| ... | @@ -5777,12 +5797,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -5777,12 +5797,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5777 | // register is the fastest way to zero a register. | 5797 | // register is the fastest way to zero a register. |
| 5778 | return self.asmRegisterRegister(.xor, reg.to32(), reg.to32()); | 5798 | return self.asmRegisterRegister(.xor, reg.to32(), reg.to32()); |
| 5779 | } | 5799 | } |
| 5780 | if (ty.isSignedInt() and x <= math.maxInt(i32)) { | 5800 | if (ty.isSignedInt()) { |
| 5781 | return self.asmRegisterImmediate( | 5801 | const signed_x = @bitCast(i64, x); |
| 5782 | .mov, | 5802 | if (math.minInt(i32) <= signed_x and signed_x <= math.maxInt(i32)) { |
| 5783 | registerAlias(reg, abi_size), | 5803 | return self.asmRegisterImmediate( |
| 5784 | Immediate.s(@intCast(i32, @bitCast(i64, x))), | 5804 | .mov, |
| 5785 | ); | 5805 | registerAlias(reg, abi_size), |
| | 5806 | Immediate.s(@intCast(i32, signed_x)), |
| | 5807 | ); |
| | 5808 | } |
| 5786 | } | 5809 | } |
| 5787 | return self.asmRegisterImmediate( | 5810 | return self.asmRegisterImmediate( |
| 5788 | .mov, | 5811 | .mov, |