authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-03-03 22:32:03+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-03-05 08:56:01+01:00
log691ec964efd50307a498fa35b715b52da144b857
tree9a27b7c1103c1cda3e0435fc59c16f1d8a9fa09b
parente3121accacaa2b9debaa60e0d4e8188de0b6a2f4
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: implement bitwise binary operations

for integers with bit sizes <= 64

3 files changed, 55 insertions(+), 37 deletions(-)

src/arch/aarch64/CodeGen.zig+47-37
......@@ -564,11 +564,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
564564 .cmp_gt => try self.airCmp(inst, .gt),
565565 .cmp_neq => try self.airCmp(inst, .neq),
566566
567 .bool_and => try self.airBoolOp(inst),
568 .bool_or => try self.airBoolOp(inst),
569 .bit_and => try self.airBitAnd(inst),
570 .bit_or => try self.airBitOr(inst),
571 .xor => try self.airXor(inst),
567 .bool_and => try self.airBinOp(inst),
568 .bool_or => try self.airBinOp(inst),
569 .bit_and => try self.airBinOp(inst),
570 .bit_or => try self.airBinOp(inst),
571 .xor => try self.airBinOp(inst),
572572 .shr, .shr_exact => try self.airShr(inst),
573573
574574 .alloc => try self.airAlloc(inst),
......@@ -1110,9 +1110,19 @@ fn binOpRegister(
11101110 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
11111111
11121112 const mir_tag: Mir.Inst.Tag = switch (tag) {
1113 .add, .ptr_add => .add_shifted_register,
1114 .sub, .ptr_sub => .sub_shifted_register,
1113 .add,
1114 .ptr_add,
1115 => .add_shifted_register,
1116 .sub,
1117 .ptr_sub,
1118 => .sub_shifted_register,
11151119 .mul => .mul,
1120 .bit_and,
1121 .bool_and,
1122 => .and_shifted_register,
1123 .bit_or,
1124 .bool_or,
1125 => .orr_shifted_register,
11161126 .xor => .eor_shifted_register,
11171127 else => unreachable,
11181128 };
......@@ -1133,7 +1143,12 @@ fn binOpRegister(
11331143 .rn = lhs_reg,
11341144 .rm = rhs_reg,
11351145 } },
1136 .xor => .{ .rrr_imm6_logical_shift = .{
1146 .bit_and,
1147 .bool_and,
1148 .bit_or,
1149 .bool_or,
1150 .xor,
1151 => .{ .rrr_imm6_logical_shift = .{
11371152 .rd = dest_reg,
11381153 .rn = lhs_reg,
11391154 .rm = rhs_reg,
......@@ -1311,7 +1326,7 @@ fn binOp(
13111326 // lowered to a << 1
13121327 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
13131328 } else {
1314 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
1329 return self.fail("TODO binary operations on int with bits > 64", .{});
13151330 }
13161331 },
13171332 else => unreachable,
......@@ -1324,7 +1339,29 @@ fn binOp(
13241339 => {
13251340 switch (lhs_ty.zigTypeTag()) {
13261341 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1327 .Int => return self.fail("TODO binary operations on integers", .{}),
1342 .Int => {
1343 assert(lhs_ty.eql(rhs_ty));
1344 const int_info = lhs_ty.intInfo(self.target.*);
1345 if (int_info.bits <= 64) {
1346 // TODO implement bitwise operations with immediates
1347 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1348 } else {
1349 return self.fail("TODO binary operations on int with bits > 64", .{});
1350 }
1351 },
1352 else => unreachable,
1353 }
1354 },
1355 .bool_and,
1356 .bool_or,
1357 => {
1358 switch (lhs_ty.zigTypeTag()) {
1359 .Bool => {
1360 assert(lhs != .immediate); // should have been handled by Sema
1361 assert(rhs != .immediate); // should have been handled by Sema
1362
1363 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1364 },
13281365 else => unreachable,
13291366 }
13301367 },
......@@ -1444,24 +1481,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
14441481 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
14451482}
14461483
1447fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void {
1448 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1449 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement bitwise and for {}", .{self.target.cpu.arch});
1450 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1451}
1452
1453fn airBitOr(self: *Self, inst: Air.Inst.Index) !void {
1454 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1455 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement bitwise or for {}", .{self.target.cpu.arch});
1456 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1457}
1458
1459fn airXor(self: *Self, inst: Air.Inst.Index) !void {
1460 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1461 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement xor for {}", .{self.target.cpu.arch});
1462 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1463}
1464
14651484fn airShl(self: *Self, inst: Air.Inst.Index) !void {
14661485 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
14671486 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 {
29692988 return self.finishAir(inst, .dead, .{ branch.operand, .none, .none });
29702989}
29712990
2972fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
2973 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2974 const air_tags = self.air.instructions.items(.tag);
2975 _ = air_tags;
2976
2977 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement boolean operations for {}", .{self.target.cpu.arch});
2978 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2979}
2980
29812991fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
29822992 const block_data = self.blocks.getPtr(block).?;
29832993
src/arch/aarch64/Emit.zig+4
......@@ -108,7 +108,9 @@ pub fn emitMir(
108108 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),
109109 .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),
110110
111 .and_shifted_register => try emit.mirLogicalShiftedRegister(inst),
111112 .eor_shifted_register => try emit.mirLogicalShiftedRegister(inst),
113 .orr_shifted_register => try emit.mirLogicalShiftedRegister(inst),
112114
113115 .load_memory_got => try emit.mirLoadMemoryPie(inst),
114116 .load_memory_direct => try emit.mirLoadMemoryPie(inst),
......@@ -660,7 +662,9 @@ fn mirLogicalShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
660662 const imm6 = rrr_imm6_logical_shift.imm6;
661663
662664 switch (tag) {
665 .and_shifted_register => try emit.writeInstruction(Instruction.andShiftedRegister(rd, rn, rm, shift, imm6)),
663666 .eor_shifted_register => try emit.writeInstruction(Instruction.eorShiftedRegister(rd, rn, rm, shift, imm6)),
667 .orr_shifted_register => try emit.writeInstruction(Instruction.orrShiftedRegister(rd, rn, rm, shift, imm6)),
664668 else => unreachable,
665669 }
666670}
src/arch/aarch64/Mir.zig+4
......@@ -28,6 +28,8 @@ pub const Inst = struct {
2828 add_immediate,
2929 /// Add (shifted register)
3030 add_shifted_register,
31 /// Bitwise AND (shifted register)
32 and_shifted_register,
3133 /// Branch conditionally
3234 b_cond,
3335 /// Branch
......@@ -108,6 +110,8 @@ pub const Inst = struct {
108110 mvn,
109111 /// No Operation
110112 nop,
113 /// Bitwise inclusive OR (shifted register)
114 orr_shifted_register,
111115 /// Pseudo-instruction: Pop multiple registers
112116 pop_regs,
113117 /// Psuedo-instruction: Push multiple registers