Commit de17fe66a5

Koakuma <koachan@protonmail.com>
2022-07-09 11:04:26
stage2: sparc64: Tidy up binOp and enable more operations
sub, mul, addwrap, subwrap, mulwrap, shr, shr_exact
1 parent ab3d3b2
Changed files (1)
src
arch
sparc64
src/arch/sparc64/CodeGen.zig
@@ -499,20 +499,29 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
             .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),
 
             .add             => try self.airBinOp(inst, .add),
-            .addwrap         => @panic("TODO try self.airAddWrap(inst)"),
+            .addwrap         => try self.airBinOp(inst, .addwrap),
+            .sub             => try self.airBinOp(inst, .sub),
+            .subwrap         => try self.airBinOp(inst, .subwrap),
+            .mul             => try self.airBinOp(inst, .mul),
+            .mulwrap         => try self.airBinOp(inst, .mulwrap),
+            .shl             => try self.airBinOp(inst, .shl),
+            .shl_exact       => try self.airBinOp(inst, .shl_exact),
+            .shr             => try self.airBinOp(inst, .shr),
+            .shr_exact       => try self.airBinOp(inst, .shr_exact),
+            .bool_and        => try self.airBinOp(inst, .bool_and),
+            .bool_or         => try self.airBinOp(inst, .bool_or),
+            .bit_and         => try self.airBinOp(inst, .bit_and),
+            .bit_or          => try self.airBinOp(inst, .bit_or),
+            .xor             => try self.airBinOp(inst, .xor),
+
             .add_sat         => @panic("TODO try self.airAddSat(inst)"),
-            .sub             => @panic("TODO try self.airBinOp(inst)"),
-            .subwrap         => @panic("TODO try self.airSubWrap(inst)"),
             .sub_sat         => @panic("TODO try self.airSubSat(inst)"),
-            .mul             => @panic("TODO try self.airMul(inst)"),
-            .mulwrap         => @panic("TODO try self.airMulWrap(inst)"),
             .mul_sat         => @panic("TODO try self.airMulSat(inst)"),
-            .rem             => try self.airRem(inst),
-            .mod             => try self.airMod(inst),
-            .shl, .shl_exact => @panic("TODO try self.airShl(inst)"),
             .shl_sat         => @panic("TODO try self.airShlSat(inst)"),
             .min             => @panic("TODO try self.airMin(inst)"),
             .max             => @panic("TODO try self.airMax(inst)"),
+            .rem             => try self.airRem(inst),
+            .mod             => try self.airMod(inst),
             .slice           => try self.airSlice(inst),
 
             .sqrt,
@@ -548,13 +557,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
             .cmp_vector => @panic("TODO try self.airCmpVector(inst)"),
             .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
 
-            .bool_and        => try self.airBinOp(inst, .bool_and),
-            .bool_or         => try self.airBinOp(inst, .bool_or),
-            .bit_and         => try self.airBinOp(inst, .bit_and),
-            .bit_or          => try self.airBinOp(inst, .bit_or),
-            .xor             => try self.airBinOp(inst, .xor),
-            .shr, .shr_exact => @panic("TODO try self.airShr(inst)"),
-
             .alloc           => try self.airAlloc(inst),
             .ret_ptr         => try self.airRetPtr(inst),
             .arg             => try self.airArg(inst),
@@ -2397,6 +2399,10 @@ fn binOp(
     switch (tag) {
         .add,
         .sub,
+        .mul,
+        .bit_and,
+        .bit_or,
+        .xor,
         .cmp_eq,
         => {
             switch (lhs_ty.zigTypeTag()) {
@@ -2411,12 +2417,20 @@ fn binOp(
                         // operands
                         const lhs_immediate_ok = switch (tag) {
                             .add => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
+                            .mul => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
+                            .bit_and => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
+                            .bit_or => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
+                            .xor => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
                             .sub, .cmp_eq => false,
                             else => unreachable,
                         };
                         const rhs_immediate_ok = switch (tag) {
                             .add,
                             .sub,
+                            .mul,
+                            .bit_and,
+                            .bit_or,
+                            .xor,
                             .cmp_eq,
                             => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
                             else => unreachable,
@@ -2425,6 +2439,10 @@ fn binOp(
                         const mir_tag: Mir.Inst.Tag = switch (tag) {
                             .add => .add,
                             .sub => .sub,
+                            .mul => .mulx,
+                            .bit_and => .@"and",
+                            .bit_or => .@"or",
+                            .xor => .xor,
                             .cmp_eq => .cmp,
                             else => unreachable,
                         };
@@ -2446,72 +2464,60 @@ fn binOp(
             }
         },
 
-        .div_trunc => {
+        .addwrap,
+        .subwrap,
+        .mulwrap,
+        => {
+            const base_tag: Air.Inst.Tag = switch (tag) {
+                .addwrap => .add,
+                .subwrap => .sub,
+                .mulwrap => .mul,
+                else => unreachable,
+            };
+
+            // Generate the base operation
+            const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
+
+            // Truncate if necessary
             switch (lhs_ty.zigTypeTag()) {
                 .Vector => return self.fail("TODO binary operations on vectors", .{}),
                 .Int => {
-                    assert(lhs_ty.eql(rhs_ty, mod));
                     const int_info = lhs_ty.intInfo(self.target.*);
                     if (int_info.bits <= 64) {
-                        const rhs_immediate_ok = switch (tag) {
-                            .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
-                            else => unreachable,
-                        };
-
-                        const mir_tag: Mir.Inst.Tag = switch (tag) {
-                            .div_trunc => switch (int_info.signedness) {
-                                .signed => Mir.Inst.Tag.sdivx,
-                                .unsigned => Mir.Inst.Tag.udivx,
-                            },
-                            else => unreachable,
-                        };
-
-                        if (rhs_immediate_ok) {
-                            return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, true, metadata);
-                        } else {
-                            return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
-                        }
+                        const result_reg = result.register;
+                        try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
+                        return result;
                     } else {
-                        return self.fail("TODO binary operations on int with bits > 64", .{});
+                        return self.fail("TODO binary operations on integers > u64/i64", .{});
                     }
                 },
                 else => unreachable,
             }
         },
 
-        .mul => {
+        .div_trunc => {
             switch (lhs_ty.zigTypeTag()) {
                 .Vector => return self.fail("TODO binary operations on vectors", .{}),
                 .Int => {
                     assert(lhs_ty.eql(rhs_ty, mod));
                     const int_info = lhs_ty.intInfo(self.target.*);
                     if (int_info.bits <= 64) {
-                        // Only say yes if the operation is
-                        // commutative, i.e. we can swap both of the
-                        // operands
-                        const lhs_immediate_ok = switch (tag) {
-                            .mul => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
-                            else => unreachable,
-                        };
                         const rhs_immediate_ok = switch (tag) {
-                            .mul => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
+                            .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
                             else => unreachable,
                         };
 
                         const mir_tag: Mir.Inst.Tag = switch (tag) {
-                            .mul => .mulx,
+                            .div_trunc => switch (int_info.signedness) {
+                                .signed => Mir.Inst.Tag.sdivx,
+                                .unsigned => Mir.Inst.Tag.udivx,
+                            },
                             else => unreachable,
                         };
 
                         if (rhs_immediate_ok) {
-                            // At this point, rhs is an immediate
-                            return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata);
-                        } else if (lhs_immediate_ok) {
-                            // swap lhs and rhs
-                            // At this point, lhs is an immediate
-                            return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata);
+                            return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, true, metadata);
                         } else {
-                            // TODO convert large immediates to register before adding
                             return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
                         }
                     } else {
@@ -2552,58 +2558,6 @@ fn binOp(
             }
         },
 
-        .bit_and,
-        .bit_or,
-        .xor,
-        => {
-            switch (lhs_ty.zigTypeTag()) {
-                .Vector => return self.fail("TODO binary operations on vectors", .{}),
-                .Int => {
-                    assert(lhs_ty.eql(rhs_ty, mod));
-                    const int_info = lhs_ty.intInfo(self.target.*);
-                    if (int_info.bits <= 64) {
-                        // Only say yes if the operation is
-                        // commutative, i.e. we can swap both of the
-                        // operands
-                        const lhs_immediate_ok = switch (tag) {
-                            .bit_and,
-                            .bit_or,
-                            .xor,
-                            => lhs == .immediate and lhs.immediate <= std.math.maxInt(u13),
-                            else => unreachable,
-                        };
-                        const rhs_immediate_ok = switch (tag) {
-                            .bit_and,
-                            .bit_or,
-                            .xor,
-                            => rhs == .immediate and rhs.immediate <= std.math.maxInt(u13),
-                            else => unreachable,
-                        };
-
-                        const mir_tag: Mir.Inst.Tag = switch (tag) {
-                            .bit_and => .@"and",
-                            .bit_or => .@"or",
-                            .xor => .xor,
-                            else => unreachable,
-                        };
-
-                        if (rhs_immediate_ok) {
-                            return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata);
-                        } else if (lhs_immediate_ok) {
-                            // swap lhs and rhs
-                            return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata);
-                        } else {
-                            // TODO convert large immediates to register before adding
-                            return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
-                        }
-                    } else {
-                        return self.fail("TODO binary operations on int with bits > 64", .{});
-                    }
-                },
-                else => unreachable,
-            }
-        },
-
         .bool_and,
         .bool_or,
         => {
@@ -2624,36 +2578,41 @@ fn binOp(
             }
         },
 
-        .shl => {
+        .shl,
+        .shr,
+        => {
             const base_tag: Air.Inst.Tag = switch (tag) {
                 .shl => .shl_exact,
+                .shr => .shr_exact,
                 else => unreachable,
             };
 
-            // Generate a shl_exact/shr_exact
+            // Generate the base operation
             const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
 
             // Truncate if necessary
-            switch (tag) {
-                .shl => switch (lhs_ty.zigTypeTag()) {
-                    .Vector => return self.fail("TODO binary operations on vectors", .{}),
-                    .Int => {
-                        const int_info = lhs_ty.intInfo(self.target.*);
-                        if (int_info.bits <= 64) {
-                            const result_reg = result.register;
-                            try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
-                            return result;
-                        } else {
-                            return self.fail("TODO binary operations on integers > u64/i64", .{});
-                        }
-                    },
-                    else => unreachable,
+            switch (lhs_ty.zigTypeTag()) {
+                .Vector => return self.fail("TODO binary operations on vectors", .{}),
+                .Int => {
+                    const int_info = lhs_ty.intInfo(self.target.*);
+                    if (int_info.bits <= 64) {
+                        // 32 and 64 bit operands doesn't need truncating
+                        if (int_info.bits == 32 or int_info.bits == 64) return result;
+
+                        const result_reg = result.register;
+                        try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
+                        return result;
+                    } else {
+                        return self.fail("TODO binary operations on integers > u64/i64", .{});
+                    }
                 },
                 else => unreachable,
             }
         },
 
-        .shl_exact => {
+        .shl_exact,
+        .shr_exact,
+        => {
             switch (lhs_ty.zigTypeTag()) {
                 .Vector => return self.fail("TODO binary operations on vectors", .{}),
                 .Int => {
@@ -2662,7 +2621,11 @@ fn binOp(
                         const rhs_immediate_ok = rhs == .immediate;
 
                         const mir_tag: Mir.Inst.Tag = switch (tag) {
-                            .shl_exact => .sllx,
+                            .shl_exact => if (int_info.bits <= 32) Mir.Inst.Tag.sll else Mir.Inst.Tag.sllx,
+                            .shr_exact => switch (int_info.signedness) {
+                                .signed => if (int_info.bits <= 32) Mir.Inst.Tag.sra else Mir.Inst.Tag.srax,
+                                .unsigned => if (int_info.bits <= 32) Mir.Inst.Tag.srl else Mir.Inst.Tag.srlx,
+                            },
                             else => unreachable,
                         };
 
@@ -2769,7 +2732,21 @@ fn binOpImmediate(
                 .rs2_or_imm = .{ .imm = @intCast(u12, rhs.immediate) },
             },
         },
-        .sllx => .{
+        .sll,
+        .srl,
+        .sra,
+        => .{
+            .shift = .{
+                .is_imm = true,
+                .rd = dest_reg,
+                .rs1 = lhs_reg,
+                .rs2_or_imm = .{ .imm = @intCast(u5, rhs.immediate) },
+            },
+        },
+        .sllx,
+        .srlx,
+        .srax,
+        => .{
             .shift = .{
                 .is_imm = true,
                 .rd = dest_reg,
@@ -2893,7 +2870,13 @@ fn binOpRegister(
                 .rs2_or_imm = .{ .rs2 = rhs_reg },
             },
         },
-        .sllx => .{
+        .sll,
+        .srl,
+        .sra,
+        .sllx,
+        .srlx,
+        .srax,
+        => .{
             .shift = .{
                 .is_imm = false,
                 .rd = dest_reg,