authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-03-08 22:47:43+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-03-13 11:32:04+01:00
log03dddc8d9c7613aff877f0dcf0efe0193869ef73
treee3aba1a4b859fe33aa29713801aee664cb3ac3f4
parent2036af94e97f0ac16293556423c144ec9e1b8226
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: implement bit shifts with register operands


4 files changed, 111 insertions(+), 15 deletions(-)

src/arch/aarch64/CodeGen.zig+34-15
......@@ -541,7 +541,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
541541 .mul_sat => try self.airMulSat(inst),
542542 .rem => try self.airRem(inst),
543543 .mod => try self.airMod(inst),
544 .shl, .shl_exact => try self.airShl(inst),
544 .shl, .shl_exact => try self.airBinOp(inst),
545545 .shl_sat => try self.airShlSat(inst),
546546 .min => try self.airMin(inst),
547547 .max => try self.airMax(inst),
......@@ -581,7 +581,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
581581 .bit_and => try self.airBinOp(inst),
582582 .bit_or => try self.airBinOp(inst),
583583 .xor => try self.airBinOp(inst),
584 .shr, .shr_exact => try self.airShr(inst),
584 .shr, .shr_exact => try self.airBinOp(inst),
585585
586586 .alloc => try self.airAlloc(inst),
587587 .ret_ptr => try self.airRetPtr(inst),
......@@ -1156,6 +1156,15 @@ fn binOpRegister(
11561156 .bit_or,
11571157 .bool_or,
11581158 => .orr_shifted_register,
1159 .shl,
1160 .shl_exact,
1161 => .lsl_register,
1162 .shr,
1163 .shr_exact,
1164 => switch (lhs_ty.intInfo(self.target.*).signedness) {
1165 .signed => Mir.Inst.Tag.asr_register,
1166 .unsigned => Mir.Inst.Tag.lsr_register,
1167 },
11591168 .xor => .eor_shifted_register,
11601169 else => unreachable,
11611170 };
......@@ -1171,7 +1180,12 @@ fn binOpRegister(
11711180 .imm6 = 0,
11721181 .shift = .lsl,
11731182 } },
1174 .mul => .{ .rrr = .{
1183 .mul,
1184 .shl,
1185 .shl_exact,
1186 .shr,
1187 .shr_exact,
1188 => .{ .rrr = .{
11751189 .rd = dest_reg,
11761190 .rn = lhs_reg,
11771191 .rm = rhs_reg,
......@@ -1385,6 +1399,23 @@ fn binOp(
13851399 else => unreachable,
13861400 }
13871401 },
1402 .shl,
1403 .shr,
1404 => {
1405 switch (lhs_ty.zigTypeTag()) {
1406 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1407 .Int => {
1408 const int_info = lhs_ty.intInfo(self.target.*);
1409 if (int_info.bits <= 64) {
1410 // TODO immediate shifts
1411 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1412 } else {
1413 return self.fail("TODO binary operations on int with bits > 64", .{});
1414 }
1415 },
1416 else => unreachable,
1417 }
1418 },
13881419 .bool_and,
13891420 .bool_or,
13901421 => {
......@@ -1514,24 +1545,12 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
15141545 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
15151546}
15161547
1517fn airShl(self: *Self, inst: Air.Inst.Index) !void {
1518 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1519 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl for {}", .{self.target.cpu.arch});
1520 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1521}
1522
15231548fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
15241549 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
15251550 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
15261551 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
15271552}
15281553
1529fn airShr(self: *Self, inst: Air.Inst.Index) !void {
1530 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1531 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shr for {}", .{self.target.cpu.arch});
1532 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1533}
1534
15351554fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
15361555 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
15371556 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement .optional_payload for {}", .{self.target.cpu.arch});
src/arch/aarch64/Emit.zig+19
......@@ -80,6 +80,10 @@ pub fn emitMir(
8080 .cmp_immediate => try emit.mirAddSubtractImmediate(inst),
8181 .sub_immediate => try emit.mirAddSubtractImmediate(inst),
8282
83 .asr_register => try emit.mirShiftRegister(inst),
84 .lsl_register => try emit.mirShiftRegister(inst),
85 .lsr_register => try emit.mirShiftRegister(inst),
86
8387 .b_cond => try emit.mirConditionalBranchImmediate(inst),
8488
8589 .b => try emit.mirBranch(inst),
......@@ -469,6 +473,21 @@ fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
469473 }
470474}
471475
476fn mirShiftRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
477 const tag = emit.mir.instructions.items(.tag)[inst];
478 const rrr = emit.mir.instructions.items(.data)[inst].rrr;
479 const rd = rrr.rd;
480 const rn = rrr.rn;
481 const rm = rrr.rm;
482
483 switch (tag) {
484 .asr_register => try emit.writeInstruction(Instruction.asrv(rd, rn, rm)),
485 .lsl_register => try emit.writeInstruction(Instruction.lslv(rd, rn, rm)),
486 .lsr_register => try emit.writeInstruction(Instruction.lsrv(rd, rn, rm)),
487 else => unreachable,
488 }
489}
490
472491fn mirConditionalBranchImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
473492 const tag = emit.mir.instructions.items(.tag)[inst];
474493 const inst_cond = emit.mir.instructions.items(.data)[inst].inst_cond;
src/arch/aarch64/Mir.zig+6
......@@ -30,6 +30,8 @@ pub const Inst = struct {
3030 add_shifted_register,
3131 /// Bitwise AND (shifted register)
3232 and_shifted_register,
33 /// Arithmetic Shift Right (register)
34 asr_register,
3335 /// Branch conditionally
3436 b_cond,
3537 /// Branch
......@@ -96,6 +98,10 @@ pub const Inst = struct {
9698 ldrh_immediate,
9799 /// Load Register Halfword (register)
98100 ldrh_register,
101 /// Logical Shift Left (register)
102 lsl_register,
103 /// Logical Shift Right (register)
104 lsr_register,
99105 /// Move (to/from SP)
100106 mov_to_from_sp,
101107 /// Move (register)
src/arch/aarch64/bits.zig+52
......@@ -356,6 +356,16 @@ pub const Instruction = union(enum) {
356356 op54: u2,
357357 sf: u1,
358358 },
359 data_processing_2_source: packed struct {
360 rd: u5,
361 rn: u5,
362 opcode: u6,
363 rm: u5,
364 fixed_1: u8 = 0b11010110,
365 s: u1,
366 fixed_2: u1 = 0b0,
367 sf: u1,
368 },
359369
360370 pub const Condition = enum(u4) {
361371 /// Integer: Equal
......@@ -479,6 +489,7 @@ pub const Instruction = union(enum) {
479489 .compare_and_branch => |v| @as(u32, v.rt) | (@as(u32, v.imm19) << 5) | (@as(u32, v.op) << 24) | (@as(u32, v.fixed) << 25) | (@as(u32, v.sf) << 31),
480490 .conditional_select => |v| @as(u32, v.rd) | @as(u32, v.rn) << 5 | @as(u32, v.op2) << 10 | @as(u32, v.cond) << 12 | @as(u32, v.rm) << 16 | @as(u32, v.fixed) << 21 | @as(u32, v.s) << 29 | @as(u32, v.op) << 30 | @as(u32, v.sf) << 31,
481491 .data_processing_3_source => |v| @bitCast(u32, v),
492 .data_processing_2_source => |v| @bitCast(u32, v),
482493 };
483494 }
484495
......@@ -1031,6 +1042,29 @@ pub const Instruction = union(enum) {
10311042 };
10321043 }
10331044
1045 fn dataProcessing2Source(
1046 s: u1,
1047 opcode: u6,
1048 rd: Register,
1049 rn: Register,
1050 rm: Register,
1051 ) Instruction {
1052 return Instruction{
1053 .data_processing_2_source = .{
1054 .rd = rd.enc(),
1055 .rn = rn.enc(),
1056 .opcode = opcode,
1057 .rm = rm.enc(),
1058 .s = s,
1059 .sf = switch (rd.size()) {
1060 32 => 0b0,
1061 64 => 0b1,
1062 else => unreachable, // unexpected register size
1063 },
1064 },
1065 };
1066 }
1067
10341068 // Helper functions for assembly syntax functions
10351069
10361070 // Move wide (immediate)
......@@ -1393,6 +1427,20 @@ pub const Instruction = union(enum) {
13931427 pub fn mneg(rd: Register, rn: Register, rm: Register) Instruction {
13941428 return msub(rd, rn, rm, .xzr);
13951429 }
1430
1431 // Data processing (2 source)
1432
1433 pub fn lslv(rd: Register, rn: Register, rm: Register) Instruction {
1434 return dataProcessing2Source(0b0, 0b001000, rd, rn, rm);
1435 }
1436
1437 pub fn lsrv(rd: Register, rn: Register, rm: Register) Instruction {
1438 return dataProcessing2Source(0b0, 0b001001, rd, rn, rm);
1439 }
1440
1441 pub fn asrv(rd: Register, rn: Register, rm: Register) Instruction {
1442 return dataProcessing2Source(0b0, 0b001010, rd, rn, rm);
1443 }
13961444};
13971445
13981446test {
......@@ -1570,6 +1618,10 @@ test "serialize instructions" {
15701618 .inst = Instruction.eorImmediate(.x3, .x5, 0b000000, 0b000000, 0b1),
15711619 .expected = 0b1_10_100100_1_000000_000000_00101_00011,
15721620 },
1621 .{ // lslv x6, x9, x10
1622 .inst = Instruction.lslv(.x6, .x9, .x10),
1623 .expected = 0b1_0_0_11010110_01010_0010_00_01001_00110,
1624 },
15731625 };
15741626
15751627 for (testcases) |case| {