authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-11 00:09:24+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-11 20:05:50+01:00
log21630ea17f1db8791c86ccb6b5e64c7390c52f61
tree262e4be686e4cb29f997e62c6091a785299b0e5a
parent6e1da365038856d9fbff690f187dc0a5c0933440

x86_64: apply couple of tweaks and pass behavior tests


3 files changed, 46 insertions(+), 20 deletions(-)

src/arch/x86_64/CodeGen.zig+41-18
...@@ -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 lower2869 // 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 }
36043608
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 // TODO5259 // TODO
5256 // We have a positive stack offset value but we want a twos complement negative5260 // 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], immediate5262 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 we5417 // 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,
src/arch/x86_64/Emit.zig+4-1
...@@ -341,7 +341,10 @@ fn mirMovsx(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -341,7 +341,10 @@ fn mirMovsx(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
341 else => unreachable, // TODO341 else => unreachable, // TODO
342 }342 }
343343
344 const mnemonic: Instruction.Mnemonic = if (op1.bitSize() == 64 and op2.bitSize() == 32) .movsxd else .movsx;344 const mnemonic: Instruction.Mnemonic = switch (op1.bitSize()) {
345 32, 64 => if (op2.bitSize() == 32) .movsxd else .movsx,
346 else => .movsx,
347 };
345348
346 return emit.encode(mnemonic, .{349 return emit.encode(mnemonic, .{
347 .op1 = op1,350 .op1 = op1,
src/arch/x86_64/bits.zig+1-1
...@@ -542,7 +542,7 @@ pub const Immediate = union(enum) {...@@ -542,7 +542,7 @@ pub const Immediate = union(enum) {
542 .signed => |x| switch (bit_size) {542 .signed => |x| switch (bit_size) {
543 1, 8 => @bitCast(u8, @intCast(i8, x)),543 1, 8 => @bitCast(u8, @intCast(i8, x)),
544 16 => @bitCast(u16, @intCast(i16, x)),544 16 => @bitCast(u16, @intCast(i16, x)),
545 32 => @bitCast(u32, @intCast(i32, x)),545 32, 64 => @bitCast(u32, x),
546 else => unreachable,546 else => unreachable,
547 },547 },
548 .unsigned => |x| switch (bit_size) {548 .unsigned => |x| switch (bit_size) {