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 {...@@ -894,6 +894,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
894 const ty_op = self.air.instructions.items(.data)[inst].ty_op;894 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
895 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {895 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
896 const operand = try self.resolveInst(ty_op.operand);896 const operand = try self.resolveInst(ty_op.operand);
897 const operand_ty = self.air.typeOf(ty_op.operand);
897 switch (operand) {898 switch (operand) {
898 .dead => unreachable,899 .dead => unreachable,
899 .unreach => unreachable,900 .unreach => unreachable,
...@@ -924,7 +925,14 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -924,7 +925,14 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
924 break :result r;925 break :result r;
925 },926 },
926 else => {927 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 }
928 },936 },
929 }937 }
930 };938 };
...@@ -1013,6 +1021,7 @@ fn binOpRegister(...@@ -1013,6 +1021,7 @@ fn binOpRegister(
1013 const mir_tag: Mir.Inst.Tag = switch (tag) {1021 const mir_tag: Mir.Inst.Tag = switch (tag) {
1014 .add => .add_shifted_register,1022 .add => .add_shifted_register,
1015 .sub => .sub_shifted_register,1023 .sub => .sub_shifted_register,
1024 .xor => .eor_shifted_register,
1016 else => unreachable,1025 else => unreachable,
1017 };1026 };
1018 const mir_data: Mir.Inst.Data = switch (tag) {1027 const mir_data: Mir.Inst.Data = switch (tag) {
...@@ -1025,6 +1034,13 @@ fn binOpRegister(...@@ -1025,6 +1034,13 @@ fn binOpRegister(
1025 .imm6 = 0,1034 .imm6 = 0,
1026 .shift = .lsl,1035 .shift = .lsl,
1027 } },1036 } },
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 } },
1028 else => unreachable,1044 else => unreachable,
1029 };1045 };
10301046
...@@ -1137,6 +1153,7 @@ fn binOp(...@@ -1137,6 +1153,7 @@ fn binOp(
1137 rhs_ty: Type,1153 rhs_ty: Type,
1138) !MCValue {1154) !MCValue {
1139 switch (tag) {1155 switch (tag) {
1156 // Arithmetic operations on integers and floats
1140 .add,1157 .add,
1141 .sub,1158 .sub,
1142 => {1159 => {
...@@ -1177,6 +1194,19 @@ fn binOp(...@@ -1177,6 +1194,19 @@ fn binOp(
1177 else => unreachable,1194 else => unreachable,
1178 }1195 }
1179 },1196 },
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 },
1180 .ptr_add,1210 .ptr_add,
1181 .ptr_sub,1211 .ptr_sub,
1182 => return self.fail("TODO ptr_add, ptr_sub", .{}),1212 => return self.fail("TODO ptr_add, ptr_sub", .{}),
src/arch/aarch64/Emit.zig+30-4
...@@ -106,6 +106,8 @@ pub fn emitMir(...@@ -106,6 +106,8 @@ pub fn emitMir(
106 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),106 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),
107 .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),107 .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),
108108
109 .eor_shifted_register => try emit.mirLogicalShiftedRegister(inst),
110
109 .load_memory => try emit.mirLoadMemory(inst),111 .load_memory => try emit.mirLoadMemory(inst),
110112
111 .ldp => try emit.mirLoadStoreRegisterPair(inst),113 .ldp => try emit.mirLoadStoreRegisterPair(inst),
...@@ -134,6 +136,7 @@ pub fn emitMir(...@@ -134,6 +136,7 @@ pub fn emitMir(
134136
135 .mov_register => try emit.mirMoveRegister(inst),137 .mov_register => try emit.mirMoveRegister(inst),
136 .mov_to_from_sp => try emit.mirMoveRegister(inst),138 .mov_to_from_sp => try emit.mirMoveRegister(inst),
139 .mvn => try emit.mirMoveRegister(inst),
137140
138 .movk => try emit.mirMoveWideImmediate(inst),141 .movk => try emit.mirMoveWideImmediate(inst),
139 .movz => try emit.mirMoveWideImmediate(inst),142 .movz => try emit.mirMoveWideImmediate(inst),
...@@ -638,6 +641,21 @@ fn mirConditionalSelect(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -638,6 +641,21 @@ fn mirConditionalSelect(emit: *Emit, inst: Mir.Inst.Index) !void {
638 }641 }
639}642}
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
641fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {659fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {
642 assert(emit.mir.instructions.items(.tag)[inst] == .load_memory);660 assert(emit.mir.instructions.items(.tag)[inst] == .load_memory);
643 const payload = emit.mir.instructions.items(.data)[inst].payload;661 const payload = emit.mir.instructions.items(.data)[inst].payload;
...@@ -821,11 +839,19 @@ fn mirLoadStoreRegisterRegister(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -821,11 +839,19 @@ fn mirLoadStoreRegisterRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
821839
822fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void {840fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
823 const tag = emit.mir.instructions.items(.tag)[inst];841 const tag = emit.mir.instructions.items(.tag)[inst];
824 const rr = emit.mir.instructions.items(.data)[inst].rr;
825
826 switch (tag) {842 switch (tag) {
827 .mov_register => try emit.writeInstruction(Instruction.orr(rr.rd, .xzr, rr.rn, Instruction.Shift.none)),843 .mov_register => {
828 .mov_to_from_sp => try emit.writeInstruction(Instruction.add(rr.rd, rr.rn, 0, false)),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 },
829 else => unreachable,855 else => unreachable,
830 }856 }
831}857}
src/arch/aarch64/Mir.zig+24
...@@ -54,6 +54,8 @@ pub const Inst = struct {...@@ -54,6 +54,8 @@ pub const Inst = struct {
54 dbg_epilogue_begin,54 dbg_epilogue_begin,
55 /// Pseudo-instruction: Update debug line55 /// Pseudo-instruction: Update debug line
56 dbg_line,56 dbg_line,
57 /// Bitwise Exclusive OR (shifted register)
58 eor_shifted_register,
57 /// Pseudo-instruction: Load memory59 /// Pseudo-instruction: Load memory
58 ///60 ///
59 /// Payload is `LoadMemory`61 /// Payload is `LoadMemory`
...@@ -88,6 +90,8 @@ pub const Inst = struct {...@@ -88,6 +90,8 @@ pub const Inst = struct {
88 movz,90 movz,
89 /// Multiply91 /// Multiply
90 mul,92 mul,
93 /// Bitwise NOT
94 mvn,
91 /// No Operation95 /// No Operation
92 nop,96 nop,
93 /// Pseudo-instruction: Pop multiple registers97 /// Pseudo-instruction: Pop multiple registers
...@@ -217,6 +221,15 @@ pub const Inst = struct {...@@ -217,6 +221,15 @@ pub const Inst = struct {
217 imm12: u12,221 imm12: u12,
218 sh: u1 = 0,222 sh: u1 = 0,
219 },223 },
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 },
220 /// Two registers233 /// Two registers
221 ///234 ///
222 /// Used by e.g. mul235 /// Used by e.g. mul
...@@ -235,6 +248,17 @@ pub const Inst = struct {...@@ -235,6 +248,17 @@ pub const Inst = struct {
235 imm6: u6,248 imm6: u6,
236 shift: bits.Instruction.AddSubtractShiftedRegisterShift,249 shift: bits.Instruction.AddSubtractShiftedRegisterShift,
237 },250 },
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 },
238 /// Two registers and a LoadStoreOffsetImmediate262 /// Two registers and a LoadStoreOffsetImmediate
239 ///263 ///
240 /// Used by e.g. str_immediate264 /// Used by e.g. str_immediate
src/arch/aarch64/bits.zig+77-43
...@@ -344,23 +344,6 @@ pub const Instruction = union(enum) {...@@ -344,23 +344,6 @@ pub const Instruction = union(enum) {
344 sf: u1,344 sf: u1,
345 },345 },
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
364 pub const Condition = enum(u4) {347 pub const Condition = enum(u4) {
365 /// Integer: Equal348 /// Integer: Equal
366 /// Floating point: Equal349 /// Floating point: Equal
...@@ -819,25 +802,28 @@ pub const Instruction = union(enum) {...@@ -819,25 +802,28 @@ pub const Instruction = union(enum) {
819 };802 };
820 }803 }
821804
805 pub const LogicalShiftedRegisterShift = enum(u2) { lsl, lsr, asr, ror };
806
822 fn logicalShiftedRegister(807 fn logicalShiftedRegister(
823 opc: u2,808 opc: u2,
824 n: u1,809 n: u1,
825 shift: Shift,
826 rd: Register,810 rd: Register,
827 rn: Register,811 rn: Register,
828 rm: Register,812 rm: Register,
813 shift: LogicalShiftedRegisterShift,
814 amount: u6,
829 ) Instruction {815 ) Instruction {
830 switch (rd.size()) {816 switch (rd.size()) {
831 32 => {817 32 => {
832 assert(shift.amount < 32);818 assert(amount < 32);
833 return Instruction{819 return Instruction{
834 .logical_shifted_register = .{820 .logical_shifted_register = .{
835 .rd = rd.id(),821 .rd = rd.id(),
836 .rn = rn.id(),822 .rn = rn.id(),
837 .imm6 = shift.amount,823 .imm6 = amount,
838 .rm = rm.id(),824 .rm = rm.id(),
839 .n = n,825 .n = n,
840 .shift = @enumToInt(shift.shift),826 .shift = @enumToInt(shift),
841 .opc = opc,827 .opc = opc,
842 .sf = 0b0,828 .sf = 0b0,
843 },829 },
...@@ -848,10 +834,10 @@ pub const Instruction = union(enum) {...@@ -848,10 +834,10 @@ pub const Instruction = union(enum) {
848 .logical_shifted_register = .{834 .logical_shifted_register = .{
849 .rd = rd.id(),835 .rd = rd.id(),
850 .rn = rn.id(),836 .rn = rn.id(),
851 .imm6 = shift.amount,837 .imm6 = amount,
852 .rm = rm.id(),838 .rm = rm.id(),
853 .n = n,839 .n = n,
854 .shift = @enumToInt(shift.shift),840 .shift = @enumToInt(shift),
855 .opc = opc,841 .opc = opc,
856 .sf = 0b1,842 .sf = 0b1,
857 },843 },
...@@ -1159,36 +1145,84 @@ pub const Instruction = union(enum) {...@@ -1159,36 +1145,84 @@ pub const Instruction = union(enum) {
11591145
1160 // Logical (shifted register)1146 // Logical (shifted register)
11611147
1162 pub fn @"and"(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1148 pub fn @"and"(
1163 return logicalShiftedRegister(0b00, 0b0, shift, rd, rn, rm);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);
1164 }1156 }
11651157
1166 pub fn bic(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1158 pub fn bic(
1167 return logicalShiftedRegister(0b00, 0b1, shift, rd, rn, rm);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);
1168 }1166 }
11691167
1170 pub fn orr(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1168 pub fn orr(
1171 return logicalShiftedRegister(0b01, 0b0, shift, rd, rn, rm);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);
1172 }1176 }
11731177
1174 pub fn orn(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1178 pub fn orn(
1175 return logicalShiftedRegister(0b01, 0b1, shift, rd, rn, rm);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);
1176 }1186 }
11771187
1178 pub fn eor(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1188 pub fn eor(
1179 return logicalShiftedRegister(0b10, 0b0, shift, rd, rn, rm);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);
1180 }1196 }
11811197
1182 pub fn eon(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1198 pub fn eon(
1183 return logicalShiftedRegister(0b10, 0b1, shift, rd, rn, rm);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);
1184 }1206 }
11851207
1186 pub fn ands(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1208 pub fn ands(
1187 return logicalShiftedRegister(0b11, 0b0, shift, rd, rn, rm);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);
1188 }1216 }
11891217
1190 pub fn bics(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction {1218 pub fn bics(
1191 return logicalShiftedRegister(0b11, 0b1, shift, rd, rn, rm);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);
1192 }1226 }
11931227
1194 // Add/subtract (immediate)1228 // Add/subtract (immediate)
...@@ -1316,11 +1350,11 @@ test "serialize instructions" {...@@ -1316,11 +1350,11 @@ test "serialize instructions" {
13161350
1317 const testcases = [_]Testcase{1351 const testcases = [_]Testcase{
1318 .{ // orr x0, xzr, x11352 .{ // orr x0, xzr, x1
1319 .inst = Instruction.orr(.x0, .xzr, .x1, Instruction.Shift.none),1353 .inst = Instruction.orr(.x0, .xzr, .x1, .lsl, 0),
1320 .expected = 0b1_01_01010_00_0_00001_000000_11111_00000,1354 .expected = 0b1_01_01010_00_0_00001_000000_11111_00000,
1321 },1355 },
1322 .{ // orn x0, xzr, x11356 .{ // orn x0, xzr, x1
1323 .inst = Instruction.orn(.x0, .xzr, .x1, Instruction.Shift.none),1357 .inst = Instruction.orn(.x0, .xzr, .x1, .lsl, 0),
1324 .expected = 0b1_01_01010_00_1_00001_000000_11111_00000,1358 .expected = 0b1_01_01010_00_1_00001_000000_11111_00000,
1325 },1359 },
1326 .{ // movz x1, #41360 .{ // movz x1, #4
...@@ -1440,11 +1474,11 @@ test "serialize instructions" {...@@ -1440,11 +1474,11 @@ test "serialize instructions" {
1440 .expected = 0b10_101_0_001_1_0000010_00010_11111_00001,1474 .expected = 0b10_101_0_001_1_0000010_00010_11111_00001,
1441 },1475 },
1442 .{ // and x0, x4, x21476 .{ // and x0, x4, x2
1443 .inst = Instruction.@"and"(.x0, .x4, .x2, .{}),1477 .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0),
1444 .expected = 0b1_00_01010_00_0_00010_000000_00100_00000,1478 .expected = 0b1_00_01010_00_0_00010_000000_00100_00000,
1445 },1479 },
1446 .{ // and x0, x4, x2, lsl #0x81480 .{ // 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),
1448 .expected = 0b1_00_01010_00_0_00010_001000_00100_00000,1482 .expected = 0b1_00_01010_00_0_00010_001000_00100_00000,
1449 },1483 },
1450 .{ // add x0, x10, #101484 .{ // add x0, x10, #10