authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-11-24 19:35:28+07:00
committergravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-12-10 21:32:00+07:00
log644593ab18a2150a5b412d586fde2fcfbb1461ea
tree5cd0bd25342bc345ea1c5f954659edf0e708e9a2
parentb4b7a404cfa0cfdc212fa66351789a199acb6e0c

stage2: sparc64: Implement airMinMax


1 files changed, 94 insertions(+), 2 deletions(-)

src/arch/sparc64/CodeGen.zig+94-2
...@@ -521,8 +521,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -521,8 +521,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
521 .sub_sat => try self.airSubSat(inst),521 .sub_sat => try self.airSubSat(inst),
522 .mul_sat => try self.airMulSat(inst),522 .mul_sat => try self.airMulSat(inst),
523 .shl_sat => try self.airShlSat(inst),523 .shl_sat => try self.airShlSat(inst),
524 .min => @panic("TODO try self.airMin(inst)"),524 .min, .max => try self.airMinMax(inst),
525 .max => @panic("TODO try self.airMax(inst)"),
526 .rem => try self.airRem(inst),525 .rem => try self.airRem(inst),
527 .mod => try self.airMod(inst),526 .mod => try self.airMod(inst),
528 .slice => try self.airSlice(inst),527 .slice => try self.airSlice(inst),
...@@ -1737,6 +1736,22 @@ fn airMemset(self: *Self, inst: Air.Inst.Index) !void {...@@ -1737,6 +1736,22 @@ fn airMemset(self: *Self, inst: Air.Inst.Index) !void {
1737 return self.fail("TODO implement airMemset for {}", .{self.target.cpu.arch});1736 return self.fail("TODO implement airMemset for {}", .{self.target.cpu.arch});
1738}1737}
17391738
1739fn airMinMax(self: *Self, inst: Air.Inst.Index) !void {
1740 const tag = self.air.instructions.items(.tag)[inst];
1741 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1742 const lhs = try self.resolveInst(bin_op.lhs);
1743 const rhs = try self.resolveInst(bin_op.rhs);
1744 const lhs_ty = self.air.typeOf(bin_op.lhs);
1745 const rhs_ty = self.air.typeOf(bin_op.rhs);
1746
1747 const result: MCValue = if (self.liveness.isUnused(inst))
1748 .dead
1749 else
1750 try self.minMax(tag, lhs, rhs, lhs_ty, rhs_ty);
1751
1752 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1753}
1754
1740fn airMod(self: *Self, inst: Air.Inst.Index) !void {1755fn airMod(self: *Self, inst: Air.Inst.Index) !void {
1741 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1756 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1742 const lhs = try self.resolveInst(bin_op.lhs);1757 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -4195,6 +4210,83 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -4195,6 +4210,83 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
4195 }4210 }
4196}4211}
41974212
4213fn minMax(
4214 self: *Self,
4215 tag: Air.Inst.Tag,
4216 lhs: MCValue,
4217 rhs: MCValue,
4218 lhs_ty: Type,
4219 rhs_ty: Type,
4220) InnerError!MCValue {
4221 const mod = self.bin_file.options.module.?;
4222 assert(lhs_ty.eql(rhs_ty, mod));
4223 switch (lhs_ty.zigTypeTag()) {
4224 .Float => return self.fail("TODO min/max on floats", .{}),
4225 .Vector => return self.fail("TODO min/max on vectors", .{}),
4226 .Int => {
4227 const int_info = lhs_ty.intInfo(self.target.*);
4228 if (int_info.bits <= 64) {
4229 // TODO skip register setting when one of the operands
4230 // is a small (fits in i13) immediate.
4231 const rhs_is_register = rhs == .register;
4232 const rhs_reg = if (rhs_is_register)
4233 rhs.register
4234 else
4235 try self.register_manager.allocReg(null, gp);
4236 const rhs_lock = self.register_manager.lockReg(rhs_reg);
4237 defer if (rhs_lock) |reg| self.register_manager.unlockReg(reg);
4238 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
4239
4240 const result_reg = try self.register_manager.allocReg(null, gp);
4241 const result_lock = self.register_manager.lockReg(result_reg);
4242 defer if (result_lock) |reg| self.register_manager.unlockReg(reg);
4243 try self.genSetReg(lhs_ty, result_reg, lhs);
4244
4245 const cond_choose_rhs: Instruction.ICondition = switch (tag) {
4246 .max => switch (int_info.signedness) {
4247 .signed => Instruction.ICondition.gt,
4248 .unsigned => Instruction.ICondition.gu,
4249 },
4250 .min => switch (int_info.signedness) {
4251 .signed => Instruction.ICondition.lt,
4252 .unsigned => Instruction.ICondition.cs,
4253 },
4254 else => unreachable,
4255 };
4256
4257 _ = try self.addInst(.{
4258 .tag = .cmp,
4259 .data = .{
4260 .arithmetic_2op = .{
4261 .is_imm = false,
4262 .rs1 = result_reg,
4263 .rs2_or_imm = .{ .rs2 = rhs_reg },
4264 },
4265 },
4266 });
4267
4268 _ = try self.addInst(.{
4269 .tag = .movcc,
4270 .data = .{
4271 .conditional_move_int = .{
4272 .is_imm = false,
4273 .ccr = .xcc,
4274 .cond = .{ .icond = cond_choose_rhs },
4275 .rd = result_reg,
4276 .rs2_or_imm = .{ .rs2 = rhs_reg },
4277 },
4278 },
4279 });
4280
4281 return MCValue{ .register = result_reg };
4282 } else {
4283 return self.fail("TODO min/max on integers > u64/i64", .{});
4284 }
4285 },
4286 else => unreachable,
4287 }
4288}
4289
4198fn parseRegName(name: []const u8) ?Register {4290fn parseRegName(name: []const u8) ?Register {
4199 if (@hasDecl(Register, "parseRegName")) {4291 if (@hasDecl(Register, "parseRegName")) {
4200 return Register.parseRegName(name);4292 return Register.parseRegName(name);