stage2 AArch64: implement bitwise binary operations

for integers with bit sizes <= 64
This commit is contained in:
joachimschmidt557 2022-03-03 22:32:03 +01:00
parent e3121accac
commit 691ec964ef
No known key found for this signature in database
GPG Key ID: E0B575BE2884ACC5
3 changed files with 55 additions and 37 deletions

View File

@ -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).?;

View File

@ -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,
}
}

View File

@ -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