diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index 538b989658..9d2613c7d8 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/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,6 +2464,37 @@ fn binOp( } }, + .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 => { + 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, + } + }, + .div_trunc => { switch (lhs_ty.zigTypeTag()) { .Vector => return self.fail("TODO binary operations on vectors", .{}), @@ -2479,49 +2528,6 @@ fn binOp( } }, - .mul => { - 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), - else => unreachable, - }; - - const mir_tag: Mir.Inst.Tag = switch (tag) { - .mul => .mulx, - 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); - } 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, - } - }, - .ptr_add => { switch (lhs_ty.zigTypeTag()) { .Pointer => { @@ -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,