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 {...@@ -564,11 +564,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
564 .cmp_gt => try self.airCmp(inst, .gt),564 .cmp_gt => try self.airCmp(inst, .gt),
565 .cmp_neq => try self.airCmp(inst, .neq),565 .cmp_neq => try self.airCmp(inst, .neq),
566566
567 .bool_and => try self.airBoolOp(inst),567 .bool_and => try self.airBinOp(inst),
568 .bool_or => try self.airBoolOp(inst),568 .bool_or => try self.airBinOp(inst),
569 .bit_and => try self.airBitAnd(inst),569 .bit_and => try self.airBinOp(inst),
570 .bit_or => try self.airBitOr(inst),570 .bit_or => try self.airBinOp(inst),
571 .xor => try self.airXor(inst),571 .xor => try self.airBinOp(inst),
572 .shr, .shr_exact => try self.airShr(inst),572 .shr, .shr_exact => try self.airShr(inst),
573573
574 .alloc => try self.airAlloc(inst),574 .alloc => try self.airAlloc(inst),
...@@ -1110,9 +1110,19 @@ fn binOpRegister(...@@ -1110,9 +1110,19 @@ fn binOpRegister(
1110 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);1110 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
11111111
1112 const mir_tag: Mir.Inst.Tag = switch (tag) {1112 const mir_tag: Mir.Inst.Tag = switch (tag) {
1113 .add, .ptr_add => .add_shifted_register,1113 .add,
1114 .sub, .ptr_sub => .sub_shifted_register,1114 .ptr_add,
1115 => .add_shifted_register,
1116 .sub,
1117 .ptr_sub,
1118 => .sub_shifted_register,
1115 .mul => .mul,1119 .mul => .mul,
1120 .bit_and,
1121 .bool_and,
1122 => .and_shifted_register,
1123 .bit_or,
1124 .bool_or,
1125 => .orr_shifted_register,
1116 .xor => .eor_shifted_register,1126 .xor => .eor_shifted_register,
1117 else => unreachable,1127 else => unreachable,
1118 };1128 };
...@@ -1133,7 +1143,12 @@ fn binOpRegister(...@@ -1133,7 +1143,12 @@ fn binOpRegister(
1133 .rn = lhs_reg,1143 .rn = lhs_reg,
1134 .rm = rhs_reg,1144 .rm = rhs_reg,
1135 } },1145 } },
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 = .{
1137 .rd = dest_reg,1152 .rd = dest_reg,
1138 .rn = lhs_reg,1153 .rn = lhs_reg,
1139 .rm = rhs_reg,1154 .rm = rhs_reg,
...@@ -1311,7 +1326,7 @@ fn binOp(...@@ -1311,7 +1326,7 @@ fn binOp(
1311 // lowered to a << 11326 // lowered to a << 1
1312 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);1327 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1313 } else {1328 } 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", .{});
1315 }1330 }
1316 },1331 },
1317 else => unreachable,1332 else => unreachable,
...@@ -1324,7 +1339,29 @@ fn binOp(...@@ -1324,7 +1339,29 @@ fn binOp(
1324 => {1339 => {
1325 switch (lhs_ty.zigTypeTag()) {1340 switch (lhs_ty.zigTypeTag()) {
1326 .Vector => return self.fail("TODO binary operations on vectors", .{}),1341 .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 },
1328 else => unreachable,1365 else => unreachable,
1329 }1366 }
1330 },1367 },
...@@ -1444,24 +1481,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {...@@ -1444,24 +1481,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
1444 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1481 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1445}1482}
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
1465fn airShl(self: *Self, inst: Air.Inst.Index) !void {1484fn airShl(self: *Self, inst: Air.Inst.Index) !void {
1466 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1485 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1467 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl for {}", .{self.target.cpu.arch});1486 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 {...@@ -2969,15 +2988,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
2969 return self.finishAir(inst, .dead, .{ branch.operand, .none, .none });2988 return self.finishAir(inst, .dead, .{ branch.operand, .none, .none });
2970}2989}
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
2981fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {2991fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
2982 const block_data = self.blocks.getPtr(block).?;2992 const block_data = self.blocks.getPtr(block).?;
29832993
src/arch/aarch64/Emit.zig+4
...@@ -108,7 +108,9 @@ pub fn emitMir(...@@ -108,7 +108,9 @@ pub fn emitMir(
108 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),108 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),
109 .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),109 .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),
110110
111 .and_shifted_register => try emit.mirLogicalShiftedRegister(inst),
111 .eor_shifted_register => try emit.mirLogicalShiftedRegister(inst),112 .eor_shifted_register => try emit.mirLogicalShiftedRegister(inst),
113 .orr_shifted_register => try emit.mirLogicalShiftedRegister(inst),
112114
113 .load_memory_got => try emit.mirLoadMemoryPie(inst),115 .load_memory_got => try emit.mirLoadMemoryPie(inst),
114 .load_memory_direct => try emit.mirLoadMemoryPie(inst),116 .load_memory_direct => try emit.mirLoadMemoryPie(inst),
...@@ -660,7 +662,9 @@ fn mirLogicalShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -660,7 +662,9 @@ fn mirLogicalShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
660 const imm6 = rrr_imm6_logical_shift.imm6;662 const imm6 = rrr_imm6_logical_shift.imm6;
661663
662 switch (tag) {664 switch (tag) {
665 .and_shifted_register => try emit.writeInstruction(Instruction.andShiftedRegister(rd, rn, rm, shift, imm6)),
663 .eor_shifted_register => try emit.writeInstruction(Instruction.eorShiftedRegister(rd, rn, rm, shift, imm6)),666 .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)),
664 else => unreachable,668 else => unreachable,
665 }669 }
666}670}
src/arch/aarch64/Mir.zig+4
...@@ -28,6 +28,8 @@ pub const Inst = struct {...@@ -28,6 +28,8 @@ pub const Inst = struct {
28 add_immediate,28 add_immediate,
29 /// Add (shifted register)29 /// Add (shifted register)
30 add_shifted_register,30 add_shifted_register,
31 /// Bitwise AND (shifted register)
32 and_shifted_register,
31 /// Branch conditionally33 /// Branch conditionally
32 b_cond,34 b_cond,
33 /// Branch35 /// Branch
...@@ -108,6 +110,8 @@ pub const Inst = struct {...@@ -108,6 +110,8 @@ pub const Inst = struct {
108 mvn,110 mvn,
109 /// No Operation111 /// No Operation
110 nop,112 nop,
113 /// Bitwise inclusive OR (shifted register)
114 orr_shifted_register,
111 /// Pseudo-instruction: Pop multiple registers115 /// Pseudo-instruction: Pop multiple registers
112 pop_regs,116 pop_regs,
113 /// Psuedo-instruction: Push multiple registers117 /// Psuedo-instruction: Push multiple registers