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
28562856 .immediate => |imm| {
28572857 switch (abi_size) {
28582858 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));
28592863 try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
28602864 .base = reg.to64(),
28612865 .disp = 0,
2862 }), Immediate.u(@truncate(u32, imm)));
2866 }), immediate);
28632867 },
28642868 8 => {
28652869 // 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
35803584 const actual_tag: Mir.Inst.Tag = switch (dst_ty.tag()) {
35813585 .f32 => switch (mir_tag) {
35823586 .add => .addss,
3583 .cmp => .cmpss,
3587 .cmp => .ucomiss,
35843588 else => return self.fail(
35853589 "TODO genBinOpMir for f32 register-register with MIR tag {}",
35863590 .{mir_tag},
......@@ -3588,7 +3592,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
35883592 },
35893593 .f64 => switch (mir_tag) {
35903594 .add => .addsd,
3591 .cmp => .cmpsd,
3595 .cmp => .ucomisd,
35923596 else => return self.fail(
35933597 "TODO genBinOpMir for f64 register-register with MIR tag {}",
35943598 .{mir_tag},
......@@ -3599,7 +3603,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
35993603 .{dst_ty.fmtDebug()},
36003604 ),
36013605 };
3602 try self.asmRegisterRegister(actual_tag, dst_reg.to128(), src_reg.to128());
3606 return self.asmRegisterRegister(actual_tag, dst_reg.to128(), src_reg.to128());
36033607 }
36043608
36053609 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
52555259 // TODO
52565260 // We have a positive stack offset value but we want a twos complement negative
52575261 // 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));
52595266 try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
52605267 .base = .rsp,
52615268 .disp = -stack_offset,
5262 }), Immediate.u(@intCast(u32, imm)));
5269 }), immediate);
52635270 },
52645271 8 => {
52655272 const reg = try self.copyToTmpRegister(ty, mcv);
......@@ -5340,10 +5347,19 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
53405347 if (!self.wantSafety())
53415348 return; // The already existing value will do just fine.
53425349 // TODO Upgrade this to a memset call when we have that available.
5343 switch (ty.abiSize(self.target.*)) {
5344 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }, opts),
5345 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }, opts),
5346 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }, opts),
5350 switch (abi_size) {
5351 1, 2, 4 => {
5352 const value: u64 = switch (abi_size) {
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 },
53475363 8 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa }, opts),
53485364 else => |x| return self.genInlineMemset(
53495365 .{ .stack_offset = stack_offset },
......@@ -5385,13 +5401,17 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
53855401 try self.asmMemoryImmediate(.mov, Memory.sib(.byte, .{
53865402 .base = base_reg,
53875403 .disp = -stack_offset,
5388 }), Immediate.u(@truncate(u32, x_big)));
5404 }), Immediate.u(@truncate(u8, x_big)));
53895405 },
53905406 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));
53915411 try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
53925412 .base = base_reg,
53935413 .disp = -stack_offset,
5394 }), Immediate.u(@truncate(u32, x_big)));
5414 }), immediate);
53955415 },
53965416 8 => {
53975417 // 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
57775797 // register is the fastest way to zero a register.
57785798 return self.asmRegisterRegister(.xor, reg.to32(), reg.to32());
57795799 }
5780 if (ty.isSignedInt() and x <= math.maxInt(i32)) {
5781 return self.asmRegisterImmediate(
5782 .mov,
5783 registerAlias(reg, abi_size),
5784 Immediate.s(@intCast(i32, @bitCast(i64, x))),
5785 );
5800 if (ty.isSignedInt()) {
5801 const signed_x = @bitCast(i64, x);
5802 if (math.minInt(i32) <= signed_x and signed_x <= math.maxInt(i32)) {
5803 return self.asmRegisterImmediate(
5804 .mov,
5805 registerAlias(reg, abi_size),
5806 Immediate.s(@intCast(i32, signed_x)),
5807 );
5808 }
57865809 }
57875810 return self.asmRegisterImmediate(
57885811 .mov,
src/arch/x86_64/Emit.zig+4-1
......@@ -341,7 +341,10 @@ fn mirMovsx(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
341341 else => unreachable, // TODO
342342 }
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
346349 return emit.encode(mnemonic, .{
347350 .op1 = op1,
src/arch/x86_64/bits.zig+1-1
......@@ -542,7 +542,7 @@ pub const Immediate = union(enum) {
542542 .signed => |x| switch (bit_size) {
543543 1, 8 => @bitCast(u8, @intCast(i8, x)),
544544 16 => @bitCast(u16, @intCast(i16, x)),
545 32 => @bitCast(u32, @intCast(i32, x)),
545 32, 64 => @bitCast(u32, x),
546546 else => unreachable,
547547 },
548548 .unsigned => |x| switch (bit_size) {