mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
stage2 AArch64: implement bitwise binary operations
for integers with bit sizes <= 64
This commit is contained in:
parent
e3121accac
commit
691ec964ef
@ -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).?;
|
||||
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user