From 6218d70d09cf60e3c1d83cdd5b49ea9eed3d5259 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Wed, 15 Jun 2022 23:23:38 +0700 Subject: [PATCH] stage2: sparc64: Implement airBinOp for and, or, and xor --- src/arch/sparc64/CodeGen.zig | 66 ++++++++++++++++++++++++++++++++++-- src/arch/sparc64/Emit.zig | 1 + src/arch/sparc64/Mir.zig | 1 + 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index 4c8ba89dd3..80c4468531 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/src/arch/sparc64/CodeGen.zig @@ -563,9 +563,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .bool_and => @panic("TODO try self.airBoolOp(inst)"), .bool_or => @panic("TODO try self.airBoolOp(inst)"), - .bit_and => @panic("TODO try self.airBitAnd(inst)"), - .bit_or => @panic("TODO try self.airBitOr(inst)"), - .xor => @panic("TODO try self.airXor(inst)"), + .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), @@ -2093,6 +2093,58 @@ 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, + } + }, + .shl => { const base_tag: Air.Inst.Tag = switch (tag) { .shl => .shl_exact, @@ -2221,6 +2273,10 @@ fn binOpImmediate( const mir_data: Mir.Inst.Data = switch (mir_tag) { .add, .addcc, + .@"and", + .@"or", + .xor, + .xnor, .mulx, .subcc, => .{ @@ -2339,6 +2395,10 @@ fn binOpRegister( const mir_data: Mir.Inst.Data = switch (mir_tag) { .add, .addcc, + .@"and", + .@"or", + .xor, + .xnor, .mulx, .subcc, => .{ diff --git a/src/arch/sparc64/Emit.zig b/src/arch/sparc64/Emit.zig index 19eeec023f..e3b65d93df 100644 --- a/src/arch/sparc64/Emit.zig +++ b/src/arch/sparc64/Emit.zig @@ -93,6 +93,7 @@ pub fn emitMir( .lduw => try emit.mirArithmetic3Op(inst), .ldx => try emit.mirArithmetic3Op(inst), + .@"and" => @panic("TODO implement sparc64 and"), .@"or" => try emit.mirArithmetic3Op(inst), .xor => try emit.mirArithmetic3Op(inst), .xnor => try emit.mirArithmetic3Op(inst), diff --git a/src/arch/sparc64/Mir.zig b/src/arch/sparc64/Mir.zig index 3ed2787d8d..b46ecd9c79 100644 --- a/src/arch/sparc64/Mir.zig +++ b/src/arch/sparc64/Mir.zig @@ -73,6 +73,7 @@ pub const Inst = struct { /// A.31 Logical Operations /// This uses the arithmetic_3op field. // TODO add other operations. + @"and", @"or", xor, xnor,