authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-07-09 16:41:05+07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-09-14 16:57:31-07:00
log0464512f2efe67d9fe853c8f4fac6448d8f48b9c
treebe14fed7cbb5325bba9a32a9e8c65812c78df74d
parentde17fe66a541b3277579d351f7a362d3f07ea91d

stage2: sparc64: Implement airShlWithOverflow


1 files changed, 91 insertions(+), 1 deletions(-)

src/arch/sparc64/CodeGen.zig+91-1
...@@ -544,7 +544,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -544,7 +544,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
544 .add_with_overflow => try self.airAddSubWithOverflow(inst),544 .add_with_overflow => try self.airAddSubWithOverflow(inst),
545 .sub_with_overflow => try self.airAddSubWithOverflow(inst),545 .sub_with_overflow => try self.airAddSubWithOverflow(inst),
546 .mul_with_overflow => try self.airMulWithOverflow(inst),546 .mul_with_overflow => try self.airMulWithOverflow(inst),
547 .shl_with_overflow => @panic("TODO try self.airShlWithOverflow(inst)"),547 .shl_with_overflow => try self.airShlWithOverflow(inst),
548548
549 .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst),549 .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst),
550550
...@@ -2022,6 +2022,96 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2022,6 +2022,96 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
2022 return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none });2022 return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none });
2023}2023}
20242024
2025fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2026 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2027 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2028 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2029 const lhs = try self.resolveInst(extra.lhs);
2030 const rhs = try self.resolveInst(extra.rhs);
2031 const lhs_ty = self.air.typeOf(extra.lhs);
2032 const rhs_ty = self.air.typeOf(extra.rhs);
2033
2034 switch (lhs_ty.zigTypeTag()) {
2035 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
2036 .Int => {
2037 const int_info = lhs_ty.intInfo(self.target.*);
2038 if (int_info.bits <= 64) {
2039 try self.spillConditionFlagsIfOccupied();
2040 self.condition_flags_inst = inst;
2041
2042 const lhs_lock: ?RegisterLock = if (lhs == .register)
2043 self.register_manager.lockRegAssumeUnused(lhs.register)
2044 else
2045 null;
2046 // TODO this currently crashes stage1
2047 // defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
2048
2049 // Increase shift amount (i.e, rhs) by shamt_bits - int_info.bits
2050 // e.g if shifting a i48 then use sr*x (shamt_bits == 64) but increase rhs by 16
2051 // and if shifting a i24 then use sr* (shamt_bits == 32) but increase rhs by 8
2052 const new_rhs = switch (int_info.bits) {
2053 1...31 => if (rhs == .immediate) MCValue{
2054 .immediate = rhs.immediate + 32 - int_info.bits,
2055 } else try self.binOp(.add, rhs, .{ .immediate = 32 - int_info.bits }, rhs_ty, rhs_ty, null),
2056 33...63 => if (rhs == .immediate) MCValue{
2057 .immediate = rhs.immediate + 64 - int_info.bits,
2058 } else try self.binOp(.add, rhs, .{ .immediate = 64 - int_info.bits }, rhs_ty, rhs_ty, null),
2059 32, 64 => rhs,
2060 else => unreachable,
2061 };
2062
2063 const new_rhs_lock: ?RegisterLock = if (new_rhs == .register)
2064 self.register_manager.lockRegAssumeUnused(new_rhs.register)
2065 else
2066 null;
2067 // TODO this currently crashes stage1
2068 // defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);
2069
2070 const dest = try self.binOp(.shl, lhs, new_rhs, lhs_ty, rhs_ty, null);
2071 const dest_reg = dest.register;
2072 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
2073 defer self.register_manager.unlockReg(dest_reg_lock);
2074
2075 const shr = try self.binOp(.shr, dest, new_rhs, lhs_ty, rhs_ty, null);
2076
2077 _ = try self.addInst(.{
2078 .tag = .cmp,
2079 .data = .{ .arithmetic_2op = .{
2080 .is_imm = false,
2081 .rs1 = dest_reg,
2082 .rs2_or_imm = .{ .rs2 = shr.register },
2083 } },
2084 });
2085
2086 const cond = Instruction.ICondition.ne;
2087 const ccr = switch (int_info.bits) {
2088 1...32 => Instruction.CCR.icc,
2089 33...64 => Instruction.CCR.xcc,
2090 else => unreachable,
2091 };
2092
2093 // TODO Those should really be written as defers, however stage1 currently
2094 // panics when those are turned into defer statements so those are
2095 // written here at the end as ordinary statements.
2096 // Because of that, on failure, the lock on those registers wouldn't be
2097 // released.
2098 if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
2099 if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);
2100
2101 break :result MCValue{ .register_with_overflow = .{
2102 .reg = dest_reg,
2103 .flag = .{ .cond = cond, .ccr = ccr },
2104 } };
2105 } else {
2106 return self.fail("TODO overflow operations on other integer sizes", .{});
2107 }
2108 },
2109 else => unreachable,
2110 }
2111 };
2112 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2113}
2114
2025fn airSlice(self: *Self, inst: Air.Inst.Index) !void {2115fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
2026 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2116 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2027 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2117 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;