Commit f28b1657aa

Jacob Young <jacobly0@users.noreply.github.com>
2023-10-09 04:30:06
x86_64: implement 128-bit integer shifts in registers
1 parent 54e7f58
Changed files (1)
src
arch
src/arch/x86_64/CodeGen.zig
@@ -6427,139 +6427,233 @@ fn genShiftBinOpMir(
             }),
         }
     } else if (abi_size <= 16) {
-        const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
-        const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
-        defer self.register_manager.unlockReg(tmp_lock);
-
-        const info: struct { offsets: [2]i32, double_tag: Mir.Inst.FixedTag } = switch (tag[0]) {
-            ._l => .{ .offsets = .{ 0, 8 }, .double_tag = .{ ._ld, .sh } },
-            ._r => .{ .offsets = .{ 8, 0 }, .double_tag = .{ ._rd, .sh } },
+        const info: struct { indices: [2]u31, double_tag: Mir.Inst.FixedTag } = switch (tag[0]) {
+            ._l => .{ .indices = .{ 0, 1 }, .double_tag = .{ ._ld, .sh } },
+            ._r => .{ .indices = .{ 1, 0 }, .double_tag = .{ ._rd, .sh } },
             else => unreachable,
         };
         switch (lhs_mcv) {
-            .load_frame => |dst_frame_addr| switch (rhs_mcv) {
-                .immediate => |rhs_imm| if (rhs_imm == 0) {} else if (rhs_imm < 64) {
-                    try self.asmRegisterMemory(
-                        .{ ._, .mov },
-                        tmp_reg,
-                        Memory.sib(.qword, .{
-                            .base = .{ .frame = dst_frame_addr.index },
-                            .disp = dst_frame_addr.off + info.offsets[0],
-                        }),
-                    );
-                    try self.asmMemoryRegisterImmediate(
+            .register_pair => |lhs_regs| switch (rhs_mcv) {
+                .immediate => |rhs_imm| if (rhs_imm > 0 and rhs_imm < 64) {
+                    try self.asmRegisterRegisterImmediate(
                         info.double_tag,
-                        Memory.sib(.qword, .{
-                            .base = .{ .frame = dst_frame_addr.index },
-                            .disp = dst_frame_addr.off + info.offsets[1],
-                        }),
-                        tmp_reg,
+                        lhs_regs[info.indices[1]],
+                        lhs_regs[info.indices[0]],
                         Immediate.u(rhs_imm),
                     );
-                    try self.asmMemoryImmediate(
+                    try self.asmRegisterImmediate(
                         tag,
-                        Memory.sib(.qword, .{
-                            .base = .{ .frame = dst_frame_addr.index },
-                            .disp = dst_frame_addr.off + info.offsets[0],
-                        }),
+                        lhs_regs[info.indices[0]],
                         Immediate.u(rhs_imm),
                     );
                 } else {
                     assert(rhs_imm < 128);
-                    try self.asmRegisterMemory(
+                    try self.asmRegisterRegister(
                         .{ ._, .mov },
-                        tmp_reg,
-                        Memory.sib(.qword, .{
-                            .base = .{ .frame = dst_frame_addr.index },
-                            .disp = dst_frame_addr.off + info.offsets[0],
-                        }),
+                        lhs_regs[info.indices[1]],
+                        lhs_regs[info.indices[0]],
                     );
-                    if (rhs_imm > 64) {
-                        try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(rhs_imm - 64));
-                    }
-                    try self.asmMemoryRegister(
-                        .{ ._, .mov },
-                        Memory.sib(.qword, .{
-                            .base = .{ .frame = dst_frame_addr.index },
-                            .disp = dst_frame_addr.off + info.offsets[1],
-                        }),
-                        tmp_reg,
-                    );
-                    if (tag[0] == ._r and tag[1] == .sa) try self.asmMemoryImmediate(
+                    if (tag[0] == ._r and tag[1] == .sa) try self.asmRegisterImmediate(
                         tag,
-                        Memory.sib(.qword, .{
-                            .base = .{ .frame = dst_frame_addr.index },
-                            .disp = dst_frame_addr.off + info.offsets[0],
-                        }),
+                        lhs_regs[info.indices[0]],
                         Immediate.u(63),
-                    ) else {
-                        try self.asmRegisterRegister(.{ ._, .xor }, tmp_reg.to32(), tmp_reg.to32());
-                        try self.asmMemoryRegister(
-                            .{ ._, .mov },
-                            Memory.sib(.qword, .{
-                                .base = .{ .frame = dst_frame_addr.index },
-                                .disp = dst_frame_addr.off + info.offsets[0],
-                            }),
-                            tmp_reg,
-                        );
-                    }
-                },
-                else => {
-                    const first_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
-                    const first_lock = self.register_manager.lockRegAssumeUnused(first_reg);
-                    defer self.register_manager.unlockReg(first_lock);
-
-                    const second_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
-                    const second_lock = self.register_manager.lockRegAssumeUnused(second_reg);
-                    defer self.register_manager.unlockReg(second_lock);
-
-                    try self.genSetReg(.cl, Type.u8, rhs_mcv);
-                    try self.asmRegisterMemory(
-                        .{ ._, .mov },
-                        first_reg,
-                        Memory.sib(.qword, .{
-                            .base = .{ .frame = dst_frame_addr.index },
-                            .disp = dst_frame_addr.off + info.offsets[0],
-                        }),
+                    ) else try self.asmRegisterRegister(
+                        .{ ._, .xor },
+                        lhs_regs[info.indices[0]],
+                        lhs_regs[info.indices[0]],
                     );
-                    try self.asmRegisterMemory(
-                        .{ ._, .mov },
-                        second_reg,
-                        Memory.sib(.qword, .{
-                            .base = .{ .frame = dst_frame_addr.index },
-                            .disp = dst_frame_addr.off + info.offsets[1],
-                        }),
+                    if (rhs_imm > 64) try self.asmRegisterImmediate(
+                        tag,
+                        lhs_regs[info.indices[1]],
+                        Immediate.u(rhs_imm - 64),
                     );
+                },
+                .register => |rhs_reg| {
+                    const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
+                    const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
+                    defer self.register_manager.unlockReg(tmp_lock);
+
                     if (tag[0] == ._r and tag[1] == .sa) {
-                        try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, first_reg);
+                        try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, lhs_regs[info.indices[0]]);
                         try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(63));
                     } else try self.asmRegisterRegister(
                         .{ ._, .xor },
                         tmp_reg.to32(),
                         tmp_reg.to32(),
                     );
-                    try self.asmRegisterRegisterRegister(info.double_tag, second_reg, first_reg, .cl);
-                    try self.asmRegisterRegister(tag, first_reg, .cl);
-                    try self.asmRegisterImmediate(.{ ._, .cmp }, .cl, Immediate.u(64));
-                    try self.asmCmovccRegisterRegister(second_reg, first_reg, .ae);
-                    try self.asmCmovccRegisterRegister(first_reg, tmp_reg, .ae);
-                    try self.asmMemoryRegister(
-                        .{ ._, .mov },
-                        Memory.sib(.qword, .{
-                            .base = .{ .frame = dst_frame_addr.index },
-                            .disp = dst_frame_addr.off + info.offsets[1],
-                        }),
-                        second_reg,
+                    try self.asmRegisterRegisterRegister(
+                        info.double_tag,
+                        lhs_regs[info.indices[1]],
+                        lhs_regs[info.indices[0]],
+                        registerAlias(rhs_reg, 1),
                     );
-                    try self.asmMemoryRegister(
-                        .{ ._, .mov },
-                        Memory.sib(.qword, .{
-                            .base = .{ .frame = dst_frame_addr.index },
-                            .disp = dst_frame_addr.off + info.offsets[0],
-                        }),
-                        first_reg,
+                    try self.asmRegisterRegister(
+                        tag,
+                        lhs_regs[info.indices[0]],
+                        registerAlias(rhs_reg, 1),
+                    );
+                    try self.asmRegisterImmediate(
+                        .{ ._, .cmp },
+                        registerAlias(rhs_reg, 1),
+                        Immediate.u(64),
                     );
+                    try self.asmCmovccRegisterRegister(
+                        lhs_regs[info.indices[1]],
+                        lhs_regs[info.indices[0]],
+                        .ae,
+                    );
+                    try self.asmCmovccRegisterRegister(lhs_regs[info.indices[0]], tmp_reg, .ae);
                 },
+                else => return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{
+                    @tagName(lhs_mcv),
+                    @tagName(rhs_mcv),
+                }),
+            },
+            .load_frame => |dst_frame_addr| {
+                const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
+                const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
+                defer self.register_manager.unlockReg(tmp_lock);
+
+                switch (rhs_mcv) {
+                    .immediate => |rhs_imm| if (rhs_imm > 0 and rhs_imm < 64) {
+                        try self.asmRegisterMemory(
+                            .{ ._, .mov },
+                            tmp_reg,
+                            Memory.sib(.qword, .{
+                                .base = .{ .frame = dst_frame_addr.index },
+                                .disp = dst_frame_addr.off + info.indices[0] * 8,
+                            }),
+                        );
+                        try self.asmMemoryRegisterImmediate(
+                            info.double_tag,
+                            Memory.sib(.qword, .{
+                                .base = .{ .frame = dst_frame_addr.index },
+                                .disp = dst_frame_addr.off + info.indices[1] * 8,
+                            }),
+                            tmp_reg,
+                            Immediate.u(rhs_imm),
+                        );
+                        try self.asmMemoryImmediate(
+                            tag,
+                            Memory.sib(.qword, .{
+                                .base = .{ .frame = dst_frame_addr.index },
+                                .disp = dst_frame_addr.off + info.indices[0] * 8,
+                            }),
+                            Immediate.u(rhs_imm),
+                        );
+                    } else {
+                        assert(rhs_imm < 128);
+                        try self.asmRegisterMemory(
+                            .{ ._, .mov },
+                            tmp_reg,
+                            Memory.sib(.qword, .{
+                                .base = .{ .frame = dst_frame_addr.index },
+                                .disp = dst_frame_addr.off + info.indices[0] * 8,
+                            }),
+                        );
+                        if (rhs_imm > 64) try self.asmRegisterImmediate(
+                            tag,
+                            tmp_reg,
+                            Immediate.u(rhs_imm - 64),
+                        );
+                        try self.asmMemoryRegister(
+                            .{ ._, .mov },
+                            Memory.sib(.qword, .{
+                                .base = .{ .frame = dst_frame_addr.index },
+                                .disp = dst_frame_addr.off + info.indices[1] * 8,
+                            }),
+                            tmp_reg,
+                        );
+                        if (tag[0] == ._r and tag[1] == .sa) try self.asmMemoryImmediate(
+                            tag,
+                            Memory.sib(.qword, .{
+                                .base = .{ .frame = dst_frame_addr.index },
+                                .disp = dst_frame_addr.off + info.indices[0] * 8,
+                            }),
+                            Immediate.u(63),
+                        ) else {
+                            try self.asmRegisterRegister(.{ ._, .xor }, tmp_reg.to32(), tmp_reg.to32());
+                            try self.asmMemoryRegister(
+                                .{ ._, .mov },
+                                Memory.sib(.qword, .{
+                                    .base = .{ .frame = dst_frame_addr.index },
+                                    .disp = dst_frame_addr.off + info.indices[0] * 8,
+                                }),
+                                tmp_reg,
+                            );
+                        }
+                    },
+                    .register => |rhs_reg| {
+                        const first_reg =
+                            try self.register_manager.allocReg(null, abi.RegisterClass.gp);
+                        const first_lock = self.register_manager.lockRegAssumeUnused(first_reg);
+                        defer self.register_manager.unlockReg(first_lock);
+
+                        const second_reg =
+                            try self.register_manager.allocReg(null, abi.RegisterClass.gp);
+                        const second_lock = self.register_manager.lockRegAssumeUnused(second_reg);
+                        defer self.register_manager.unlockReg(second_lock);
+
+                        try self.asmRegisterMemory(
+                            .{ ._, .mov },
+                            first_reg,
+                            Memory.sib(.qword, .{
+                                .base = .{ .frame = dst_frame_addr.index },
+                                .disp = dst_frame_addr.off + info.indices[0] * 8,
+                            }),
+                        );
+                        try self.asmRegisterMemory(
+                            .{ ._, .mov },
+                            second_reg,
+                            Memory.sib(.qword, .{
+                                .base = .{ .frame = dst_frame_addr.index },
+                                .disp = dst_frame_addr.off + info.indices[1] * 8,
+                            }),
+                        );
+                        if (tag[0] == ._r and tag[1] == .sa) {
+                            try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, first_reg);
+                            try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(63));
+                        } else try self.asmRegisterRegister(
+                            .{ ._, .xor },
+                            tmp_reg.to32(),
+                            tmp_reg.to32(),
+                        );
+                        try self.asmRegisterRegisterRegister(
+                            info.double_tag,
+                            second_reg,
+                            first_reg,
+                            registerAlias(rhs_reg, 1),
+                        );
+                        try self.asmRegisterRegister(tag, first_reg, registerAlias(rhs_reg, 1));
+                        try self.asmRegisterImmediate(
+                            .{ ._, .cmp },
+                            registerAlias(rhs_reg, 1),
+                            Immediate.u(64),
+                        );
+                        try self.asmCmovccRegisterRegister(second_reg, first_reg, .ae);
+                        try self.asmCmovccRegisterRegister(first_reg, tmp_reg, .ae);
+                        try self.asmMemoryRegister(
+                            .{ ._, .mov },
+                            Memory.sib(.qword, .{
+                                .base = .{ .frame = dst_frame_addr.index },
+                                .disp = dst_frame_addr.off + info.indices[1] * 8,
+                            }),
+                            second_reg,
+                        );
+                        try self.asmMemoryRegister(
+                            .{ ._, .mov },
+                            Memory.sib(.qword, .{
+                                .base = .{ .frame = dst_frame_addr.index },
+                                .disp = dst_frame_addr.off + info.indices[0] * 8,
+                            }),
+                            first_reg,
+                        );
+                    },
+                    else => return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{
+                        @tagName(lhs_mcv),
+                        @tagName(rhs_mcv),
+                    }),
+                }
             },
             else => return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{
                 @tagName(lhs_mcv),