authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-05-15 10:39:56+07:00
committergravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-05-16 23:30:54+07:00
log7245aad6895c39fee1f7897add9e18807e880213
treed352598d1ad47caed2e22cdbde497159cd048f87
parent67a1fedf8443a16da6a8e0f815ea42c2b9acff0a

stage2: sparc64: Implement airBinOp for addition


1 files changed, 42 insertions(+), 4 deletions(-)

src/arch/sparc64/CodeGen.zig+42-4
......@@ -483,7 +483,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
483483
484484 switch (air_tags[inst]) {
485485 // zig fmt: off
486 .add, .ptr_add => @panic("TODO try self.airBinOp(inst)"),
486 .add, .ptr_add => try self.airBinOp(inst),
487487 .addwrap => @panic("TODO try self.airAddWrap(inst)"),
488488 .add_sat => @panic("TODO try self.airAddSat(inst)"),
489489 .sub, .ptr_sub => @panic("TODO try self.airBinOp(inst)"),
......@@ -825,6 +825,21 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
825825 return self.finishAir(inst, mcv, .{ .none, .none, .none });
826826}
827827
828fn airBinOp(self: *Self, inst: Air.Inst.Index) !void {
829 const tag = self.air.instructions.items(.tag)[inst];
830 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
831 const lhs = try self.resolveInst(bin_op.lhs);
832 const rhs = try self.resolveInst(bin_op.rhs);
833 const lhs_ty = self.air.typeOf(bin_op.lhs);
834 const rhs_ty = self.air.typeOf(bin_op.rhs);
835
836 const result: MCValue = if (self.liveness.isUnused(inst))
837 .dead
838 else
839 try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
840 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
841}
842
828843fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
829844 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
830845 const result = try self.resolveInst(ty_op.operand);
......@@ -1601,7 +1616,7 @@ fn binOp(
16011616) InnerError!MCValue {
16021617 const mod = self.bin_file.options.module.?;
16031618 switch (tag) {
1604 .cmp_eq => {
1619 .add, .cmp_eq => {
16051620 switch (lhs_ty.zigTypeTag()) {
16061621 .Float => return self.fail("TODO binary operations on floats", .{}),
16071622 .Vector => return self.fail("TODO binary operations on vectors", .{}),
......@@ -1609,14 +1624,37 @@ fn binOp(
16091624 assert(lhs_ty.eql(rhs_ty, mod));
16101625 const int_info = lhs_ty.intInfo(self.target.*);
16111626 if (int_info.bits <= 64) {
1612 // TODO optimize for small (i13) values by putting them inside immediates
1627 // Only say yes if the operation is
1628 // commutative, i.e. we can swap both of the
1629 // operands
1630 const lhs_immediate_ok = switch (tag) {
1631 .add => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
1632 .sub, .cmp_eq => false,
1633 else => unreachable,
1634 };
1635 const rhs_immediate_ok = switch (tag) {
1636 .add,
1637 .sub,
1638 .cmp_eq,
1639 => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
1640 else => unreachable,
1641 };
16131642
16141643 const mir_tag: Mir.Inst.Tag = switch (tag) {
1644 .add => .add,
16151645 .cmp_eq => .subcc,
16161646 else => unreachable,
16171647 };
16181648
1619 return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1649 if (rhs_immediate_ok) {
1650 return try self.binOpImmediate(mir_tag, maybe_inst, lhs, rhs, lhs_ty, false);
1651 } else if (lhs_immediate_ok) {
1652 // swap lhs and rhs
1653 return try self.binOpImmediate(mir_tag, maybe_inst, rhs, lhs, rhs_ty, true);
1654 } else {
1655 // TODO convert large immediates to register before adding
1656 return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1657 }
16201658 } else {
16211659 return self.fail("TODO binary operations on int with bits > 64", .{});
16221660 }