diff options
| author | joachimschmidt557 <joachim.schmidt557@outlook.com> | 2022-03-03 22:32:03 +0100 |
|---|---|---|
| committer | joachimschmidt557 <joachim.schmidt557@outlook.com> | 2022-03-05 08:56:01 +0100 |
| commit | 691ec964efd50307a498fa35b715b52da144b857 (patch) | |
| tree | 9a27b7c1103c1cda3e0435fc59c16f1d8a9fa09b /src | |
| parent | e3121accacaa2b9debaa60e0d4e8188de0b6a2f4 (diff) | |
| download | zig-691ec964efd50307a498fa35b715b52da144b857.tar.gz zig-691ec964efd50307a498fa35b715b52da144b857.zip | |
stage2 AArch64: implement bitwise binary operations
for integers with bit sizes <= 64
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/aarch64/CodeGen.zig | 84 | ||||
| -rw-r--r-- | src/arch/aarch64/Emit.zig | 4 | ||||
| -rw-r--r-- | src/arch/aarch64/Mir.zig | 4 |
3 files changed, 55 insertions, 37 deletions
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 2c804d4840..5034850db8 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -564,11 +564,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .cmp_gt => try self.airCmp(inst, .gt), .cmp_neq => try self.airCmp(inst, .neq), - .bool_and => try self.airBoolOp(inst), - .bool_or => try self.airBoolOp(inst), - .bit_and => try self.airBitAnd(inst), - .bit_or => try self.airBitOr(inst), - .xor => try self.airXor(inst), + .bool_and => try self.airBinOp(inst), + .bool_or => try self.airBinOp(inst), + .bit_and => try self.airBinOp(inst), + .bit_or => try self.airBinOp(inst), + .xor => try self.airBinOp(inst), .shr, .shr_exact => try self.airShr(inst), .alloc => try self.airAlloc(inst), @@ -1110,9 +1110,19 @@ fn binOpRegister( if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); const mir_tag: Mir.Inst.Tag = switch (tag) { - .add, .ptr_add => .add_shifted_register, - .sub, .ptr_sub => .sub_shifted_register, + .add, + .ptr_add, + => .add_shifted_register, + .sub, + .ptr_sub, + => .sub_shifted_register, .mul => .mul, + .bit_and, + .bool_and, + => .and_shifted_register, + .bit_or, + .bool_or, + => .orr_shifted_register, .xor => .eor_shifted_register, else => unreachable, }; @@ -1133,7 +1143,12 @@ fn binOpRegister( .rn = lhs_reg, .rm = rhs_reg, } }, - .xor => .{ .rrr_imm6_logical_shift = .{ + .bit_and, + .bool_and, + .bit_or, + .bool_or, + .xor, + => .{ .rrr_imm6_logical_shift = .{ .rd = dest_reg, .rn = lhs_reg, .rm = rhs_reg, @@ -1311,7 +1326,7 @@ fn binOp( // lowered to a << 1 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); } else { - return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); + return self.fail("TODO binary operations on int with bits > 64", .{}); } }, else => unreachable, @@ -1324,7 +1339,29 @@ fn binOp( => { switch (lhs_ty.zigTypeTag()) { .Vector => return self.fail("TODO binary operations on vectors", .{}), - .Int => return self.fail("TODO binary operations on integers", .{}), + .Int => { + assert(lhs_ty.eql(rhs_ty)); + const int_info = lhs_ty.intInfo(self.target.*); + if (int_info.bits <= 64) { + // TODO implement bitwise operations with immediates + return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); + } else { + return self.fail("TODO binary operations on int with bits > 64", .{}); + } + }, + else => unreachable, + } + }, + .bool_and, + .bool_or, + => { + switch (lhs_ty.zigTypeTag()) { + .Bool => { + assert(lhs != .immediate); // should have been handled by Sema + assert(rhs != .immediate); // should have been handled by Sema + + return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); + }, else => unreachable, } }, @@ -1444,24 +1481,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); } -fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void { - const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement bitwise and for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); -} - -fn airBitOr(self: *Self, inst: Air.Inst.Index) !void { - const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement bitwise or for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); -} - -fn airXor(self: *Self, inst: Air.Inst.Index) !void { - const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement xor for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); -} - fn airShl(self: *Self, inst: Air.Inst.Index) !void { const bin_op = self.air.instructions.items(.data)[inst].bin_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl for {}", .{self.target.cpu.arch}); @@ -2969,15 +2988,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, .dead, .{ branch.operand, .none, .none }); } -fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { - const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const air_tags = self.air.instructions.items(.tag); - _ = air_tags; - - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement boolean operations for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); -} - fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { const block_data = self.blocks.getPtr(block).?; diff --git a/src/arch/aarch64/Emit.zig b/src/arch/aarch64/Emit.zig index 922aa731ef..84bb559824 100644 --- a/src/arch/aarch64/Emit.zig +++ b/src/arch/aarch64/Emit.zig @@ -108,7 +108,9 @@ pub fn emitMir( .dbg_prologue_end => try emit.mirDebugPrologueEnd(), .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(), + .and_shifted_register => try emit.mirLogicalShiftedRegister(inst), .eor_shifted_register => try emit.mirLogicalShiftedRegister(inst), + .orr_shifted_register => try emit.mirLogicalShiftedRegister(inst), .load_memory_got => try emit.mirLoadMemoryPie(inst), .load_memory_direct => try emit.mirLoadMemoryPie(inst), @@ -660,7 +662,9 @@ fn mirLogicalShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void { const imm6 = rrr_imm6_logical_shift.imm6; switch (tag) { + .and_shifted_register => try emit.writeInstruction(Instruction.andShiftedRegister(rd, rn, rm, shift, imm6)), .eor_shifted_register => try emit.writeInstruction(Instruction.eorShiftedRegister(rd, rn, rm, shift, imm6)), + .orr_shifted_register => try emit.writeInstruction(Instruction.orrShiftedRegister(rd, rn, rm, shift, imm6)), else => unreachable, } } diff --git a/src/arch/aarch64/Mir.zig b/src/arch/aarch64/Mir.zig index 7e9f8a819f..9d5837f2f5 100644 --- a/src/arch/aarch64/Mir.zig +++ b/src/arch/aarch64/Mir.zig @@ -28,6 +28,8 @@ pub const Inst = struct { add_immediate, /// Add (shifted register) add_shifted_register, + /// Bitwise AND (shifted register) + and_shifted_register, /// Branch conditionally b_cond, /// Branch @@ -108,6 +110,8 @@ pub const Inst = struct { mvn, /// No Operation nop, + /// Bitwise inclusive OR (shifted register) + orr_shifted_register, /// Pseudo-instruction: Pop multiple registers pop_regs, /// Psuedo-instruction: Push multiple registers |
