diff options
| author | Koakuma <koachan@protonmail.com> | 2022-11-24 19:35:28 +0700 |
|---|---|---|
| committer | Koakuma <koachan@protonmail.com> | 2022-12-10 21:32:00 +0700 |
| commit | 644593ab18a2150a5b412d586fde2fcfbb1461ea (patch) | |
| tree | 5cd0bd25342bc345ea1c5f954659edf0e708e9a2 /src | |
| parent | b4b7a404cfa0cfdc212fa66351789a199acb6e0c (diff) | |
| download | zig-644593ab18a2150a5b412d586fde2fcfbb1461ea.tar.gz zig-644593ab18a2150a5b412d586fde2fcfbb1461ea.zip | |
stage2: sparc64: Implement airMinMax
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/sparc64/CodeGen.zig | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index 00e08a0964..604fd3e69f 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/src/arch/sparc64/CodeGen.zig @@ -521,8 +521,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .sub_sat => try self.airSubSat(inst), .mul_sat => try self.airMulSat(inst), .shl_sat => try self.airShlSat(inst), - .min => @panic("TODO try self.airMin(inst)"), - .max => @panic("TODO try self.airMax(inst)"), + .min, .max => try self.airMinMax(inst), .rem => try self.airRem(inst), .mod => try self.airMod(inst), .slice => try self.airSlice(inst), @@ -1737,6 +1736,22 @@ fn airMemset(self: *Self, inst: Air.Inst.Index) !void { return self.fail("TODO implement airMemset for {}", .{self.target.cpu.arch}); } +fn airMinMax(self: *Self, inst: Air.Inst.Index) !void { + const tag = self.air.instructions.items(.tag)[inst]; + const bin_op = self.air.instructions.items(.data)[inst].bin_op; + const lhs = try self.resolveInst(bin_op.lhs); + const rhs = try self.resolveInst(bin_op.rhs); + const lhs_ty = self.air.typeOf(bin_op.lhs); + const rhs_ty = self.air.typeOf(bin_op.rhs); + + const result: MCValue = if (self.liveness.isUnused(inst)) + .dead + else + try self.minMax(tag, lhs, rhs, lhs_ty, rhs_ty); + + return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); +} + fn airMod(self: *Self, inst: Air.Inst.Index) !void { const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -4195,6 +4210,83 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne } } +fn minMax( + self: *Self, + tag: Air.Inst.Tag, + lhs: MCValue, + rhs: MCValue, + lhs_ty: Type, + rhs_ty: Type, +) InnerError!MCValue { + const mod = self.bin_file.options.module.?; + assert(lhs_ty.eql(rhs_ty, mod)); + switch (lhs_ty.zigTypeTag()) { + .Float => return self.fail("TODO min/max on floats", .{}), + .Vector => return self.fail("TODO min/max on vectors", .{}), + .Int => { + const int_info = lhs_ty.intInfo(self.target.*); + if (int_info.bits <= 64) { + // TODO skip register setting when one of the operands + // is a small (fits in i13) immediate. + const rhs_is_register = rhs == .register; + const rhs_reg = if (rhs_is_register) + rhs.register + else + try self.register_manager.allocReg(null, gp); + const rhs_lock = self.register_manager.lockReg(rhs_reg); + defer if (rhs_lock) |reg| self.register_manager.unlockReg(reg); + if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); + + const result_reg = try self.register_manager.allocReg(null, gp); + const result_lock = self.register_manager.lockReg(result_reg); + defer if (result_lock) |reg| self.register_manager.unlockReg(reg); + try self.genSetReg(lhs_ty, result_reg, lhs); + + const cond_choose_rhs: Instruction.ICondition = switch (tag) { + .max => switch (int_info.signedness) { + .signed => Instruction.ICondition.gt, + .unsigned => Instruction.ICondition.gu, + }, + .min => switch (int_info.signedness) { + .signed => Instruction.ICondition.lt, + .unsigned => Instruction.ICondition.cs, + }, + else => unreachable, + }; + + _ = try self.addInst(.{ + .tag = .cmp, + .data = .{ + .arithmetic_2op = .{ + .is_imm = false, + .rs1 = result_reg, + .rs2_or_imm = .{ .rs2 = rhs_reg }, + }, + }, + }); + + _ = try self.addInst(.{ + .tag = .movcc, + .data = .{ + .conditional_move_int = .{ + .is_imm = false, + .ccr = .xcc, + .cond = .{ .icond = cond_choose_rhs }, + .rd = result_reg, + .rs2_or_imm = .{ .rs2 = rhs_reg }, + }, + }, + }); + + return MCValue{ .register = result_reg }; + } else { + return self.fail("TODO min/max on integers > u64/i64", .{}); + } + }, + else => unreachable, + } +} + fn parseRegName(name: []const u8) ?Register { if (@hasDecl(Register, "parseRegName")) { return Register.parseRegName(name); |
