aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjoachimschmidt557 <joachim.schmidt557@outlook.com>2022-03-03 22:32:03 +0100
committerjoachimschmidt557 <joachim.schmidt557@outlook.com>2022-03-05 08:56:01 +0100
commit691ec964efd50307a498fa35b715b52da144b857 (patch)
tree9a27b7c1103c1cda3e0435fc59c16f1d8a9fa09b /src
parente3121accacaa2b9debaa60e0d4e8188de0b6a2f4 (diff)
downloadzig-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.zig84
-rw-r--r--src/arch/aarch64/Emit.zig4
-rw-r--r--src/arch/aarch64/Mir.zig4
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