authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-12 18:37:11+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-14 22:09:44+01:00
log1c37622659f70115b698b5924472c2268bca63a8
tree1d3d09e920a7c9b01954744c1990702dd544e360
parent3a33f313347f3fa151ba3a90c1c3b14eee3d1d1e
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: Implement not for booleans


4 files changed, 162 insertions(+), 48 deletions(-)

src/arch/aarch64/CodeGen.zig+31-1
......@@ -894,6 +894,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
894894 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
895895 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
896896 const operand = try self.resolveInst(ty_op.operand);
897 const operand_ty = self.air.typeOf(ty_op.operand);
897898 switch (operand) {
898899 .dead => unreachable,
899900 .unreach => unreachable,
......@@ -924,7 +925,14 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
924925 break :result r;
925926 },
926927 else => {
927 return self.fail("TODO implement NOT for {}", .{self.target.cpu.arch});
928 switch (operand_ty.zigTypeTag()) {
929 .Bool => {
930 // TODO convert this to mvn + and
931 const dest = try self.binOp(.xor, null, operand, .{ .immediate = 1 }, operand_ty, Type.bool);
932 break :result dest;
933 },
934 else => return self.fail("TODO bitwise not", .{}),
935 }
928936 },
929937 }
930938 };
......@@ -1013,6 +1021,7 @@ fn binOpRegister(
10131021 const mir_tag: Mir.Inst.Tag = switch (tag) {
10141022 .add => .add_shifted_register,
10151023 .sub => .sub_shifted_register,
1024 .xor => .eor_shifted_register,
10161025 else => unreachable,
10171026 };
10181027 const mir_data: Mir.Inst.Data = switch (tag) {
......@@ -1025,6 +1034,13 @@ fn binOpRegister(
10251034 .imm6 = 0,
10261035 .shift = .lsl,
10271036 } },
1037 .xor => .{ .rrr_imm6_logical_shift = .{
1038 .rd = dest_reg,
1039 .rn = lhs_reg,
1040 .rm = rhs_reg,
1041 .imm6 = 0,
1042 .shift = .lsl,
1043 } },
10281044 else => unreachable,
10291045 };
10301046
......@@ -1137,6 +1153,7 @@ fn binOp(
11371153 rhs_ty: Type,
11381154) !MCValue {
11391155 switch (tag) {
1156 // Arithmetic operations on integers and floats
11401157 .add,
11411158 .sub,
11421159 => {
......@@ -1177,6 +1194,19 @@ fn binOp(
11771194 else => unreachable,
11781195 }
11791196 },
1197 // Bitwise operations on integers
1198 .xor => {
1199 switch (lhs_ty.zigTypeTag()) {
1200 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1201 .Int => return self.fail("TODO binary operations on vectors", .{}),
1202 .Bool => {
1203 assert(lhs_ty.eql(rhs_ty));
1204 // TODO boolean operations with immediates
1205 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1206 },
1207 else => unreachable,
1208 }
1209 },
11801210 .ptr_add,
11811211 .ptr_sub,
11821212 => return self.fail("TODO ptr_add, ptr_sub", .{}),
src/arch/aarch64/Emit.zig+30-4
......@@ -106,6 +106,8 @@ pub fn emitMir(
106106 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),
107107 .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),
108108
109 .eor_shifted_register => try emit.mirLogicalShiftedRegister(inst),
110
109111 .load_memory => try emit.mirLoadMemory(inst),
110112
111113 .ldp => try emit.mirLoadStoreRegisterPair(inst),
......@@ -134,6 +136,7 @@ pub fn emitMir(
134136
135137 .mov_register => try emit.mirMoveRegister(inst),
136138 .mov_to_from_sp => try emit.mirMoveRegister(inst),
139 .mvn => try emit.mirMoveRegister(inst),
137140
138141 .movk => try emit.mirMoveWideImmediate(inst),
139142 .movz => try emit.mirMoveWideImmediate(inst),
......@@ -638,6 +641,21 @@ fn mirConditionalSelect(emit: *Emit, inst: Mir.Inst.Index) !void {
638641 }
639642}
640643
644fn mirLogicalShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
645 const tag = emit.mir.instructions.items(.tag)[inst];
646 const rrr_imm6_logical_shift = emit.mir.instructions.items(.data)[inst].rrr_imm6_logical_shift;
647 const rd = rrr_imm6_logical_shift.rd;
648 const rn = rrr_imm6_logical_shift.rn;
649 const rm = rrr_imm6_logical_shift.rm;
650 const shift = rrr_imm6_logical_shift.shift;
651 const imm6 = rrr_imm6_logical_shift.imm6;
652
653 switch (tag) {
654 .eor_shifted_register => try emit.writeInstruction(Instruction.eor(rd, rn, rm, shift, imm6)),
655 else => unreachable,
656 }
657}
658
641659fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {
642660 assert(emit.mir.instructions.items(.tag)[inst] == .load_memory);
643661 const payload = emit.mir.instructions.items(.data)[inst].payload;
......@@ -821,11 +839,19 @@ fn mirLoadStoreRegisterRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
821839
822840fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
823841 const tag = emit.mir.instructions.items(.tag)[inst];
824 const rr = emit.mir.instructions.items(.data)[inst].rr;
825
826842 switch (tag) {
827 .mov_register => try emit.writeInstruction(Instruction.orr(rr.rd, .xzr, rr.rn, Instruction.Shift.none)),
828 .mov_to_from_sp => try emit.writeInstruction(Instruction.add(rr.rd, rr.rn, 0, false)),
843 .mov_register => {
844 const rr = emit.mir.instructions.items(.data)[inst].rr;
845 try emit.writeInstruction(Instruction.orr(rr.rd, .xzr, rr.rn, .lsl, 0));
846 },
847 .mov_to_from_sp => {
848 const rr = emit.mir.instructions.items(.data)[inst].rr;
849 try emit.writeInstruction(Instruction.add(rr.rd, rr.rn, 0, false));
850 },
851 .mvn => {
852 const rr_imm6_shift = emit.mir.instructions.items(.data)[inst].rr_imm6_shift;
853 try emit.writeInstruction(Instruction.orn(rr_imm6_shift.rd, .xzr, rr_imm6_shift.rm, .lsl, 0));
854 },
829855 else => unreachable,
830856 }
831857}
src/arch/aarch64/Mir.zig+24
......@@ -54,6 +54,8 @@ pub const Inst = struct {
5454 dbg_epilogue_begin,
5555 /// Pseudo-instruction: Update debug line
5656 dbg_line,
57 /// Bitwise Exclusive OR (shifted register)
58 eor_shifted_register,
5759 /// Pseudo-instruction: Load memory
5860 ///
5961 /// Payload is `LoadMemory`
......@@ -88,6 +90,8 @@ pub const Inst = struct {
8890 movz,
8991 /// Multiply
9092 mul,
93 /// Bitwise NOT
94 mvn,
9195 /// No Operation
9296 nop,
9397 /// Pseudo-instruction: Pop multiple registers
......@@ -217,6 +221,15 @@ pub const Inst = struct {
217221 imm12: u12,
218222 sh: u1 = 0,
219223 },
224 /// Two registers and a shift (shift type and 6-bit amount)
225 ///
226 /// Used by e.g. mvn
227 rr_imm6_shift: struct {
228 rd: Register,
229 rm: Register,
230 imm6: u6,
231 shift: bits.Instruction.AddSubtractShiftedRegisterShift,
232 },
220233 /// Two registers
221234 ///
222235 /// Used by e.g. mul
......@@ -235,6 +248,17 @@ pub const Inst = struct {
235248 imm6: u6,
236249 shift: bits.Instruction.AddSubtractShiftedRegisterShift,
237250 },
251 /// Three registers and a shift (logical instruction version)
252 /// (shift type and 6-bit amount)
253 ///
254 /// Used by e.g. eor_shifted_register
255 rrr_imm6_logical_shift: struct {
256 rd: Register,
257 rn: Register,
258 rm: Register,
259 imm6: u6,
260 shift: bits.Instruction.LogicalShiftedRegisterShift,
261 },
238262 /// Two registers and a LoadStoreOffsetImmediate
239263 ///
240264 /// Used by e.g. str_immediate
src/arch/aarch64/bits.zig+77-43
......@@ -344,23 +344,6 @@ pub const Instruction = union(enum) {
344344 sf: u1,
345345 },
346346
347 pub const Shift = struct {
348 shift: Type = .lsl,
349 amount: u6 = 0,
350
351 pub const Type = enum(u2) {
352 lsl,
353 lsr,
354 asr,
355 ror,
356 };
357
358 pub const none = Shift{
359 .shift = .lsl,
360 .amount = 0,
361 };
362 };
363
364347 pub const Condition = enum(u4) {
365348 /// Integer: Equal
366349 /// Floating point: Equal
......@@ -819,25 +802,28 @@ pub const Instruction = union(enum) {
819802 };
820803 }
821804
805 pub const LogicalShiftedRegisterShift = enum(u2) { lsl, lsr, asr, ror };
806
822807 fn logicalShiftedRegister(
823808 opc: u2,
824809 n: u1,
825 shift: Shift,
826810 rd: Register,
827811 rn: Register,
828812 rm: Register,
813 shift: LogicalShiftedRegisterShift,
814 amount: u6,
829815 ) Instruction {
830816 switch (rd.size()) {
831817 32 => {
832 assert(shift.amount < 32);
818 assert(amount < 32);
833819 return Instruction{
834820 .logical_shifted_register = .{
835821 .rd = rd.id(),
836822 .rn = rn.id(),
837 .imm6 = shift.amount,
823 .imm6 = amount,
838824 .rm = rm.id(),
839825 .n = n,
840 .shift = @enumToInt(shift.shift),
826 .shift = @enumToInt(shift),
841827 .opc = opc,
842828 .sf = 0b0,
843829 },
......@@ -848,10 +834,10 @@ pub const Instruction = union(enum) {
848834 .logical_shifted_register = .{
849835 .rd = rd.id(),
850836 .rn = rn.id(),
851 .imm6 = shift.amount,
837 .imm6 = amount,
852838 .rm = rm.id(),
853839 .n = n,
854 .shift = @enumToInt(shift.shift),
840 .shift = @enumToInt(shift),
855841 .opc = opc,
856842 .sf = 0b1,
857843 },
......@@ -1159,36 +1145,84 @@ pub const Instruction = union(enum) {
11591145
11601146 // Logical (shifted register)
11611147
1162 pub fn @"and"(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {
1163 return logicalShiftedRegister(0b00, 0b0, shift, rd, rn, rm);
1148 pub fn @"and"(
1149 rd: Register,
1150 rn: Register,
1151 rm: Register,
1152 shift: LogicalShiftedRegisterShift,
1153 amount: u6,
1154 ) Instruction {
1155 return logicalShiftedRegister(0b00, 0b0, rd, rn, rm, shift, amount);
11641156 }
11651157
1166 pub fn bic(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {
1167 return logicalShiftedRegister(0b00, 0b1, shift, rd, rn, rm);
1158 pub fn bic(
1159 rd: Register,
1160 rn: Register,
1161 rm: Register,
1162 shift: LogicalShiftedRegisterShift,
1163 amount: u6,
1164 ) Instruction {
1165 return logicalShiftedRegister(0b00, 0b1, rd, rn, rm, shift, amount);
11681166 }
11691167
1170 pub fn orr(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {
1171 return logicalShiftedRegister(0b01, 0b0, shift, rd, rn, rm);
1168 pub fn orr(
1169 rd: Register,
1170 rn: Register,
1171 rm: Register,
1172 shift: LogicalShiftedRegisterShift,
1173 amount: u6,
1174 ) Instruction {
1175 return logicalShiftedRegister(0b01, 0b0, rd, rn, rm, shift, amount);
11721176 }
11731177
1174 pub fn orn(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {
1175 return logicalShiftedRegister(0b01, 0b1, shift, rd, rn, rm);
1178 pub fn orn(
1179 rd: Register,
1180 rn: Register,
1181 rm: Register,
1182 shift: LogicalShiftedRegisterShift,
1183 amount: u6,
1184 ) Instruction {
1185 return logicalShiftedRegister(0b01, 0b1, rd, rn, rm, shift, amount);
11761186 }
11771187
1178 pub fn eor(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {
1179 return logicalShiftedRegister(0b10, 0b0, shift, rd, rn, rm);
1188 pub fn eor(
1189 rd: Register,
1190 rn: Register,
1191 rm: Register,
1192 shift: LogicalShiftedRegisterShift,
1193 amount: u6,
1194 ) Instruction {
1195 return logicalShiftedRegister(0b10, 0b0, rd, rn, rm, shift, amount);
11801196 }
11811197
1182 pub fn eon(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {
1183 return logicalShiftedRegister(0b10, 0b1, shift, rd, rn, rm);
1198 pub fn eon(
1199 rd: Register,
1200 rn: Register,
1201 rm: Register,
1202 shift: LogicalShiftedRegisterShift,
1203 amount: u6,
1204 ) Instruction {
1205 return logicalShiftedRegister(0b10, 0b1, rd, rn, rm, shift, amount);
11841206 }
11851207
1186 pub fn ands(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {
1187 return logicalShiftedRegister(0b11, 0b0, shift, rd, rn, rm);
1208 pub fn ands(
1209 rd: Register,
1210 rn: Register,
1211 rm: Register,
1212 shift: LogicalShiftedRegisterShift,
1213 amount: u6,
1214 ) Instruction {
1215 return logicalShiftedRegister(0b11, 0b0, rd, rn, rm, shift, amount);
11881216 }
11891217
1190 pub fn bics(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {
1191 return logicalShiftedRegister(0b11, 0b1, shift, rd, rn, rm);
1218 pub fn bics(
1219 rd: Register,
1220 rn: Register,
1221 rm: Register,
1222 shift: LogicalShiftedRegisterShift,
1223 amount: u6,
1224 ) Instruction {
1225 return logicalShiftedRegister(0b11, 0b1, rd, rn, rm, shift, amount);
11921226 }
11931227
11941228 // Add/subtract (immediate)
......@@ -1316,11 +1350,11 @@ test "serialize instructions" {
13161350
13171351 const testcases = [_]Testcase{
13181352 .{ // orr x0, xzr, x1
1319 .inst = Instruction.orr(.x0, .xzr, .x1, Instruction.Shift.none),
1353 .inst = Instruction.orr(.x0, .xzr, .x1, .lsl, 0),
13201354 .expected = 0b1_01_01010_00_0_00001_000000_11111_00000,
13211355 },
13221356 .{ // orn x0, xzr, x1
1323 .inst = Instruction.orn(.x0, .xzr, .x1, Instruction.Shift.none),
1357 .inst = Instruction.orn(.x0, .xzr, .x1, .lsl, 0),
13241358 .expected = 0b1_01_01010_00_1_00001_000000_11111_00000,
13251359 },
13261360 .{ // movz x1, #4
......@@ -1440,11 +1474,11 @@ test "serialize instructions" {
14401474 .expected = 0b10_101_0_001_1_0000010_00010_11111_00001,
14411475 },
14421476 .{ // and x0, x4, x2
1443 .inst = Instruction.@"and"(.x0, .x4, .x2, .{}),
1477 .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0),
14441478 .expected = 0b1_00_01010_00_0_00010_000000_00100_00000,
14451479 },
14461480 .{ // and x0, x4, x2, lsl #0x8
1447 .inst = Instruction.@"and"(.x0, .x4, .x2, .{ .shift = .lsl, .amount = 0x8 }),
1481 .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0x8),
14481482 .expected = 0b1_00_01010_00_0_00010_001000_00100_00000,
14491483 },
14501484 .{ // add x0, x10, #10