authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-07-23 12:50:41-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-07-25 14:20:23-04:00
log869ef00602328f97ea8c88358310cbd34d4391ab
treeef633f331759ee9df6b4facbe7440cc498f08dd7
parentbb71a18ede1f976ad6d6bb7e84b88f0edc7d30e9

aarch64: more progress

- factor out `loadReg` - support all general system control registers in inline asm - fix asserts after iterating field offsets - fix typo in `slice_elem_val` - fix translation of argument locations

8 files changed, 721 insertions(+), 316 deletions(-)

src/codegen/aarch64.zig+1-3
...@@ -113,9 +113,7 @@ pub fn generate(...@@ -113,9 +113,7 @@ pub fn generate(
113 },113 },
114 .stack_slot => |stack_slot| {114 .stack_slot => |stack_slot| {
115 assert(stack_slot.base == .sp);115 assert(stack_slot.base == .sp);
116 passed_vi.setParent(&isel, .{116 passed_vi.changeStackSlot(&isel, named_stack_args.withOffset(stack_slot.offset));
117 .stack_slot = named_stack_args.withOffset(stack_slot.offset),
118 });
119 },117 },
120 .address, .value, .constant => unreachable,118 .address, .value, .constant => unreachable,
121 }119 }
src/codegen/aarch64/Assemble.zig+11-2
...@@ -215,6 +215,7 @@ fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct {...@@ -215,6 +215,7 @@ fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct {
215215
216const SymbolSpec = union(enum) {216const SymbolSpec = union(enum) {
217 reg: struct { format: aarch64.encoding.Register.Format, allow_sp: bool = false },217 reg: struct { format: aarch64.encoding.Register.Format, allow_sp: bool = false },
218 systemreg,
218 imm: struct {219 imm: struct {
219 type: std.builtin.Type.Int,220 type: std.builtin.Type.Int,
220 multiple_of: comptime_int = 1,221 multiple_of: comptime_int = 1,
...@@ -227,6 +228,7 @@ const SymbolSpec = union(enum) {...@@ -227,6 +228,7 @@ const SymbolSpec = union(enum) {
227 fn Storage(comptime spec: SymbolSpec) type {228 fn Storage(comptime spec: SymbolSpec) type {
228 return switch (spec) {229 return switch (spec) {
229 .reg => aarch64.encoding.Register,230 .reg => aarch64.encoding.Register,
231 .systemreg => aarch64.encoding.Register.System,
230 .imm => |imm| @Type(.{ .int = imm.type }),232 .imm => |imm| @Type(.{ .int = imm.type }),
231 .extend => Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option,233 .extend => Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option,
232 .shift => Instruction.DataProcessingRegister.Shift.Op,234 .shift => Instruction.DataProcessingRegister.Shift.Op,
...@@ -238,8 +240,7 @@ const SymbolSpec = union(enum) {...@@ -238,8 +240,7 @@ const SymbolSpec = union(enum) {
238 const Result = Storage(spec);240 const Result = Storage(spec);
239 switch (spec) {241 switch (spec) {
240 .reg => |reg_spec| {242 .reg => |reg_spec| {
241 var buf: [token_buf_len]u8 = undefined;243 const reg = Result.parse(token) orelse {
242 const reg = Result.parse(std.ascii.lowerString(&buf, token[0..@min(token.len, buf.len)])) orelse {
243 log.debug("invalid register: \"{f}\"", .{std.zig.fmtString(token)});244 log.debug("invalid register: \"{f}\"", .{std.zig.fmtString(token)});
244 return null;245 return null;
245 };246 };
...@@ -253,6 +254,14 @@ const SymbolSpec = union(enum) {...@@ -253,6 +254,14 @@ const SymbolSpec = union(enum) {
253 }254 }
254 return reg;255 return reg;
255 },256 },
257 .systemreg => {
258 const systemreg = Result.parse(token) orelse {
259 log.debug("invalid system register: \"{f}\"", .{std.zig.fmtString(token)});
260 return null;
261 };
262 assert(systemreg.op0 >= 2);
263 return systemreg;
264 },
256 .imm => |imm_spec| {265 .imm => |imm_spec| {
257 const imm = std.fmt.parseInt(Result, token, 0) catch {266 const imm = std.fmt.parseInt(Result, token, 0) catch {
258 log.debug("invalid immediate: \"{f}\"", .{std.zig.fmtString(token)});267 log.debug("invalid immediate: \"{f}\"", .{std.zig.fmtString(token)});
src/codegen/aarch64/Select.zig+263-263
...@@ -5535,7 +5535,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -5535,7 +5535,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
5535 2 => if (elem_is_vector) .ldr(elem_ra.h(), .{ .extended_register = .{5535 2 => if (elem_is_vector) .ldr(elem_ra.h(), .{ .extended_register = .{
5536 .base = base_mat.ra.x(),5536 .base = base_mat.ra.x(),
5537 .index = index_mat.ra.x(),5537 .index = index_mat.ra.x(),
5538 .extend = .{ .lsl = 0 },5538 .extend = .{ .lsl = 1 },
5539 } }) else switch (elem_vi.value.signedness(isel)) {5539 } }) else switch (elem_vi.value.signedness(isel)) {
5540 .signed => .ldrsh(elem_ra.w(), .{ .extended_register = .{5540 .signed => .ldrsh(elem_ra.w(), .{ .extended_register = .{
5541 .base = base_mat.ra.x(),5541 .base = base_mat.ra.x(),
...@@ -5558,15 +5558,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -5558,15 +5558,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
5558 .index = index_mat.ra.x(),5558 .index = index_mat.ra.x(),
5559 .extend = .{ .lsl = 3 },5559 .extend = .{ .lsl = 3 },
5560 } }),5560 } }),
5561 16 => .ldr(elem_ra.q(), .{ .extended_register = .{5561 16 => if (elem_is_vector) .ldr(elem_ra.q(), .{ .extended_register = .{
5562 .base = base_mat.ra.x(),5562 .base = base_mat.ra.x(),
5563 .index = index_mat.ra.x(),5563 .index = index_mat.ra.x(),
5564 .extend = .{ .lsl = 4 },5564 .extend = .{ .lsl = 4 },
5565 } }),5565 } }) else unreachable,
5566 });5566 });
5567 try index_mat.finish(isel);5567 try index_mat.finish(isel);
5568 try base_mat.finish(isel);5568 try base_mat.finish(isel);
5569 break :unused;
5570 } else {5569 } else {
5571 const elem_ptr_ra = try isel.allocIntReg();5570 const elem_ptr_ra = try isel.allocIntReg();
5572 defer isel.freeReg(elem_ptr_ra);5571 defer isel.freeReg(elem_ptr_ra);
...@@ -5611,66 +5610,81 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -5611,66 +5610,81 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
5611 const ptr_ty = isel.air.typeOf(bin_op.lhs, ip);5610 const ptr_ty = isel.air.typeOf(bin_op.lhs, ip);
5612 const ptr_info = ptr_ty.ptrInfo(zcu);5611 const ptr_info = ptr_ty.ptrInfo(zcu);
5613 const elem_size = elem_vi.value.size(isel);5612 const elem_size = elem_vi.value.size(isel);
5614 switch (elem_size) {5613 const elem_is_vector = elem_vi.value.isVector(isel);
5614 if (switch (elem_size) {
5615 0 => unreachable,5615 0 => unreachable,
5616 1, 2, 4, 8 => {5616 1, 2, 4, 8 => true,
5617 const elem_ra = try elem_vi.value.defReg(isel) orelse break :unused;5617 16 => elem_is_vector,
5618 const base_vi = try isel.use(bin_op.lhs);5618 else => false,
5619 const index_vi = try isel.use(bin_op.rhs);5619 }) {
5620 const base_mat = try base_vi.matReg(isel);5620 const elem_ra = try elem_vi.value.defReg(isel) orelse break :unused;
5621 const index_mat = try index_vi.matReg(isel);5621 const base_vi = try isel.use(bin_op.lhs);
5622 try isel.emit(switch (elem_size) {5622 const index_vi = try isel.use(bin_op.rhs);
5623 else => unreachable,5623 const base_mat = try base_vi.matReg(isel);
5624 1 => switch (elem_vi.value.signedness(isel)) {5624 const index_mat = try index_vi.matReg(isel);
5625 .signed => .ldrsb(elem_ra.w(), .{ .extended_register = .{5625 try isel.emit(switch (elem_size) {
5626 .base = base_mat.ra.x(),5626 else => unreachable,
5627 .index = index_mat.ra.x(),5627 1 => if (elem_is_vector) .ldr(elem_ra.b(), .{ .extended_register = .{
5628 .extend = .{ .lsl = 0 },5628 .base = base_mat.ra.x(),
5629 } }),5629 .index = index_mat.ra.x(),
5630 .unsigned => .ldrb(elem_ra.w(), .{ .extended_register = .{5630 .extend = .{ .lsl = 0 },
5631 .base = base_mat.ra.x(),5631 } }) else switch (elem_vi.value.signedness(isel)) {
5632 .index = index_mat.ra.x(),5632 .signed => .ldrsb(elem_ra.w(), .{ .extended_register = .{
5633 .extend = .{ .lsl = 0 },
5634 } }),
5635 },
5636 2 => switch (elem_vi.value.signedness(isel)) {
5637 .signed => .ldrsh(elem_ra.w(), .{ .extended_register = .{
5638 .base = base_mat.ra.x(),
5639 .index = index_mat.ra.x(),
5640 .extend = .{ .lsl = 1 },
5641 } }),
5642 .unsigned => .ldrh(elem_ra.w(), .{ .extended_register = .{
5643 .base = base_mat.ra.x(),
5644 .index = index_mat.ra.x(),
5645 .extend = .{ .lsl = 1 },
5646 } }),
5647 },
5648 4 => .ldr(elem_ra.w(), .{ .extended_register = .{
5649 .base = base_mat.ra.x(),5633 .base = base_mat.ra.x(),
5650 .index = index_mat.ra.x(),5634 .index = index_mat.ra.x(),
5651 .extend = .{ .lsl = 2 },5635 .extend = .{ .lsl = 0 },
5652 } }),5636 } }),
5653 8 => .ldr(elem_ra.x(), .{ .extended_register = .{5637 .unsigned => .ldrb(elem_ra.w(), .{ .extended_register = .{
5654 .base = base_mat.ra.x(),5638 .base = base_mat.ra.x(),
5655 .index = index_mat.ra.x(),5639 .index = index_mat.ra.x(),
5656 .extend = .{ .lsl = 3 },5640 .extend = .{ .lsl = 0 },
5657 } }),5641 } }),
5658 });5642 },
5659 try index_mat.finish(isel);5643 2 => if (elem_is_vector) .ldr(elem_ra.h(), .{ .extended_register = .{
5660 try base_mat.finish(isel);5644 .base = base_mat.ra.x(),
5661 },5645 .index = index_mat.ra.x(),
5662 else => {5646 .extend = .{ .lsl = 1 },
5663 const elem_ptr_ra = try isel.allocIntReg();5647 } }) else switch (elem_vi.value.signedness(isel)) {
5664 defer isel.freeReg(elem_ptr_ra);5648 .signed => .ldrsh(elem_ra.w(), .{ .extended_register = .{
5665 if (!try elem_vi.value.load(isel, ptr_ty.elemType2(zcu), elem_ptr_ra, .{5649 .base = base_mat.ra.x(),
5666 .@"volatile" = ptr_info.flags.is_volatile,5650 .index = index_mat.ra.x(),
5667 })) break :unused;5651 .extend = .{ .lsl = 1 },
5668 const base_vi = try isel.use(bin_op.lhs);5652 } }),
5669 const base_mat = try base_vi.matReg(isel);5653 .unsigned => .ldrh(elem_ra.w(), .{ .extended_register = .{
5670 const index_vi = try isel.use(bin_op.rhs);5654 .base = base_mat.ra.x(),
5671 try isel.elemPtr(elem_ptr_ra, base_mat.ra, .add, elem_size, index_vi);5655 .index = index_mat.ra.x(),
5672 try base_mat.finish(isel);5656 .extend = .{ .lsl = 1 },
5673 },5657 } }),
5658 },
5659 4 => .ldr(if (elem_is_vector) elem_ra.s() else elem_ra.w(), .{ .extended_register = .{
5660 .base = base_mat.ra.x(),
5661 .index = index_mat.ra.x(),
5662 .extend = .{ .lsl = 2 },
5663 } }),
5664 8 => .ldr(if (elem_is_vector) elem_ra.d() else elem_ra.x(), .{ .extended_register = .{
5665 .base = base_mat.ra.x(),
5666 .index = index_mat.ra.x(),
5667 .extend = .{ .lsl = 3 },
5668 } }),
5669 16 => if (elem_is_vector) .ldr(elem_ra.q(), .{ .extended_register = .{
5670 .base = base_mat.ra.x(),
5671 .index = index_mat.ra.x(),
5672 .extend = .{ .lsl = 4 },
5673 } }) else unreachable,
5674 });
5675 try index_mat.finish(isel);
5676 try base_mat.finish(isel);
5677 } else {
5678 const elem_ptr_ra = try isel.allocIntReg();
5679 defer isel.freeReg(elem_ptr_ra);
5680 if (!try elem_vi.value.load(isel, ptr_ty.elemType2(zcu), elem_ptr_ra, .{
5681 .@"volatile" = ptr_info.flags.is_volatile,
5682 })) break :unused;
5683 const base_vi = try isel.use(bin_op.lhs);
5684 const base_mat = try base_vi.matReg(isel);
5685 const index_vi = try isel.use(bin_op.rhs);
5686 try isel.elemPtr(elem_ptr_ra, base_mat.ra, .add, elem_size, index_vi);
5687 try base_mat.finish(isel);
5674 }5688 }
5675 }5689 }
5676 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5690 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
...@@ -6250,11 +6264,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6250,11 +6264,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
6250 try agg_part_vi.?.move(isel, elems[field_index]);6264 try agg_part_vi.?.move(isel, elems[field_index]);
6251 field_offset += field_size;6265 field_offset += field_size;
6252 }6266 }
6253 assert(field_offset == agg_vi.value.size(isel));6267 assert(loaded_struct.flagsUnordered(ip).alignment.forward(field_offset) == agg_vi.value.size(isel));
6254 },6268 },
6255 .tuple_type => |tuple_type| {6269 .tuple_type => |tuple_type| {
6256 const elems: []const Air.Inst.Ref =6270 const elems: []const Air.Inst.Ref =
6257 @ptrCast(isel.air.extra.items[ty_pl.payload..][0..tuple_type.types.len]);6271 @ptrCast(isel.air.extra.items[ty_pl.payload..][0..tuple_type.types.len]);
6272 var tuple_align: InternPool.Alignment = .@"1";
6258 var field_offset: u64 = 0;6273 var field_offset: u64 = 0;
6259 for (6274 for (
6260 tuple_type.types.get(ip),6275 tuple_type.types.get(ip),
...@@ -6263,7 +6278,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6263,7 +6278,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
6263 ) |field_ty_index, field_val, elem| {6278 ) |field_ty_index, field_val, elem| {
6264 if (field_val != .none) continue;6279 if (field_val != .none) continue;
6265 const field_ty: ZigType = .fromInterned(field_ty_index);6280 const field_ty: ZigType = .fromInterned(field_ty_index);
6266 field_offset = field_ty.abiAlignment(zcu).forward(field_offset);6281 const field_align = field_ty.abiAlignment(zcu);
6282 tuple_align = tuple_align.maxStrict(field_align);
6283 field_offset = field_align.forward(field_offset);
6267 const field_size = field_ty.abiSize(zcu);6284 const field_size = field_ty.abiSize(zcu);
6268 if (field_size == 0) continue;6285 if (field_size == 0) continue;
6269 var agg_part_it = agg_vi.value.field(agg_ty, field_offset, field_size);6286 var agg_part_it = agg_vi.value.field(agg_ty, field_offset, field_size);
...@@ -6271,7 +6288,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6271,7 +6288,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
6271 try agg_part_vi.?.move(isel, elem);6288 try agg_part_vi.?.move(isel, elem);
6272 field_offset += field_size;6289 field_offset += field_size;
6273 }6290 }
6274 assert(field_offset == agg_vi.value.size(isel));6291 assert(tuple_align.forward(field_offset) == agg_vi.value.size(isel));
6275 },6292 },
6276 else => return isel.fail("aggregate init {f}", .{isel.fmtType(agg_ty)}),6293 else => return isel.fail("aggregate init {f}", .{isel.fmtType(agg_ty)}),
6277 }6294 }
...@@ -7283,6 +7300,175 @@ fn ctzLimb(...@@ -7283,6 +7300,175 @@ fn ctzLimb(
7283 }7300 }
7284}7301}
72857302
7303fn loadReg(
7304 isel: *Select,
7305 ra: Register.Alias,
7306 size: u64,
7307 signedness: std.builtin.Signedness,
7308 base_ra: Register.Alias,
7309 offset: i65,
7310) !void {
7311 switch (size) {
7312 0 => unreachable,
7313 1 => {
7314 if (std.math.cast(u12, offset)) |unsigned_offset| return isel.emit(if (ra.isVector()) .ldr(
7315 ra.b(),
7316 .{ .unsigned_offset = .{
7317 .base = base_ra.x(),
7318 .offset = unsigned_offset,
7319 } },
7320 ) else switch (signedness) {
7321 .signed => .ldrsb(ra.w(), .{ .unsigned_offset = .{
7322 .base = base_ra.x(),
7323 .offset = unsigned_offset,
7324 } }),
7325 .unsigned => .ldrb(ra.w(), .{ .unsigned_offset = .{
7326 .base = base_ra.x(),
7327 .offset = unsigned_offset,
7328 } }),
7329 });
7330 if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(if (ra.isVector())
7331 .ldur(ra.b(), base_ra.x(), signed_offset)
7332 else switch (signedness) {
7333 .signed => .ldursb(ra.w(), base_ra.x(), signed_offset),
7334 .unsigned => .ldurb(ra.w(), base_ra.x(), signed_offset),
7335 });
7336 },
7337 2 => {
7338 if (std.math.cast(u13, offset)) |unsigned_offset| if (unsigned_offset % 2 == 0)
7339 return isel.emit(if (ra.isVector()) .ldr(
7340 ra.h(),
7341 .{ .unsigned_offset = .{
7342 .base = base_ra.x(),
7343 .offset = unsigned_offset,
7344 } },
7345 ) else switch (signedness) {
7346 .signed => .ldrsh(
7347 ra.w(),
7348 .{ .unsigned_offset = .{
7349 .base = base_ra.x(),
7350 .offset = unsigned_offset,
7351 } },
7352 ),
7353 .unsigned => .ldrh(
7354 ra.w(),
7355 .{ .unsigned_offset = .{
7356 .base = base_ra.x(),
7357 .offset = unsigned_offset,
7358 } },
7359 ),
7360 });
7361 if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(if (ra.isVector())
7362 .ldur(ra.h(), base_ra.x(), signed_offset)
7363 else switch (signedness) {
7364 .signed => .ldursh(ra.w(), base_ra.x(), signed_offset),
7365 .unsigned => .ldurh(ra.w(), base_ra.x(), signed_offset),
7366 });
7367 },
7368 3 => {
7369 const lo16_ra = try isel.allocIntReg();
7370 defer isel.freeReg(lo16_ra);
7371 try isel.emit(.orr(ra.w(), lo16_ra.w(), .{ .shifted_register = .{
7372 .register = ra.w(),
7373 .shift = .{ .lsl = 16 },
7374 } }));
7375 try isel.loadReg(ra, 1, signedness, base_ra, offset + 2);
7376 return isel.loadReg(lo16_ra, 2, .unsigned, base_ra, offset);
7377 },
7378 4 => {
7379 if (std.math.cast(u14, offset)) |unsigned_offset| if (unsigned_offset % 4 == 0) return isel.emit(.ldr(
7380 if (ra.isVector()) ra.s() else ra.w(),
7381 .{ .unsigned_offset = .{
7382 .base = base_ra.x(),
7383 .offset = unsigned_offset,
7384 } },
7385 ));
7386 if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(.ldur(
7387 if (ra.isVector()) ra.s() else ra.w(),
7388 base_ra.x(),
7389 signed_offset,
7390 ));
7391 },
7392 5, 6 => {
7393 const lo32_ra = try isel.allocIntReg();
7394 defer isel.freeReg(lo32_ra);
7395 try isel.emit(.orr(ra.x(), lo32_ra.x(), .{ .shifted_register = .{
7396 .register = ra.x(),
7397 .shift = .{ .lsl = 32 },
7398 } }));
7399 try isel.loadReg(ra, size - 4, signedness, base_ra, offset + 4);
7400 return isel.loadReg(lo32_ra, 4, .unsigned, base_ra, offset);
7401 },
7402 7 => {
7403 const lo32_ra = try isel.allocIntReg();
7404 defer isel.freeReg(lo32_ra);
7405 const lo48_ra = try isel.allocIntReg();
7406 defer isel.freeReg(lo48_ra);
7407 try isel.emit(.orr(ra.x(), lo48_ra.x(), .{ .shifted_register = .{
7408 .register = ra.x(),
7409 .shift = .{ .lsl = 32 + 16 },
7410 } }));
7411 try isel.loadReg(ra, 1, signedness, base_ra, offset + 4 + 2);
7412 try isel.emit(.orr(lo48_ra.x(), lo32_ra.x(), .{ .shifted_register = .{
7413 .register = lo48_ra.x(),
7414 .shift = .{ .lsl = 32 },
7415 } }));
7416 try isel.loadReg(lo48_ra, 2, .unsigned, base_ra, offset + 4);
7417 return isel.loadReg(lo32_ra, 4, .unsigned, base_ra, offset);
7418 },
7419 8 => {
7420 if (std.math.cast(u15, offset)) |unsigned_offset| if (unsigned_offset % 8 == 0) return isel.emit(.ldr(
7421 if (ra.isVector()) ra.d() else ra.x(),
7422 .{ .unsigned_offset = .{
7423 .base = base_ra.x(),
7424 .offset = unsigned_offset,
7425 } },
7426 ));
7427 if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(.ldur(
7428 if (ra.isVector()) ra.d() else ra.x(),
7429 base_ra.x(),
7430 signed_offset,
7431 ));
7432 },
7433 16 => {
7434 if (std.math.cast(u16, offset)) |unsigned_offset| if (unsigned_offset % 16 == 0) return isel.emit(.ldr(
7435 ra.q(),
7436 .{ .unsigned_offset = .{
7437 .base = base_ra.x(),
7438 .offset = unsigned_offset,
7439 } },
7440 ));
7441 if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(.ldur(ra.q(), base_ra.x(), signed_offset));
7442 },
7443 else => return isel.fail("bad load size: {d}", .{size}),
7444 }
7445 const ptr_ra = try isel.allocIntReg();
7446 defer isel.freeReg(ptr_ra);
7447 try isel.loadReg(ra, size, signedness, ptr_ra, 0);
7448 if (std.math.cast(u24, offset)) |pos_offset| {
7449 const lo12: u12 = @truncate(pos_offset >> 0);
7450 const hi12: u12 = @intCast(pos_offset >> 12);
7451 if (hi12 > 0) try isel.emit(.add(
7452 ptr_ra.x(),
7453 if (lo12 > 0) ptr_ra.x() else base_ra.x(),
7454 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
7455 ));
7456 if (lo12 > 0 or hi12 == 0) try isel.emit(.add(ptr_ra.x(), base_ra.x(), .{ .immediate = lo12 }));
7457 } else if (std.math.cast(u24, -offset)) |neg_offset| {
7458 const lo12: u12 = @truncate(neg_offset >> 0);
7459 const hi12: u12 = @intCast(neg_offset >> 12);
7460 if (hi12 > 0) try isel.emit(.sub(
7461 ptr_ra.x(),
7462 if (lo12 > 0) ptr_ra.x() else base_ra.x(),
7463 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
7464 ));
7465 if (lo12 > 0 or hi12 == 0) try isel.emit(.sub(ptr_ra.x(), base_ra.x(), .{ .immediate = lo12 }));
7466 } else {
7467 try isel.emit(.add(ptr_ra.x(), base_ra.x(), .{ .register = ptr_ra.x() }));
7468 try isel.movImmediate(ptr_ra.x(), @truncate(@as(u65, @bitCast(offset))));
7469 }
7470}
7471
7286fn storeReg(7472fn storeReg(
7287 isel: *Select,7473 isel: *Select,
7288 ra: Register.Alias,7474 ra: Register.Alias,
...@@ -7558,6 +7744,13 @@ pub const Value = struct {...@@ -7558,6 +7744,13 @@ pub const Value = struct {
7558 };7744 };
7559 }7745 }
75607746
7747 pub fn changeStackSlot(vi: Value.Index, isel: *Select, new_stack_slot: Indirect) void {
7748 const value = vi.get(isel);
7749 assert(value.flags.parent_tag == .stack_slot);
7750 value.flags.parent_tag = .unallocated;
7751 vi.setParent(isel, .{ .stack_slot = new_stack_slot });
7752 }
7753
7561 pub fn parent(vi: Value.Index, isel: *Select) Parent {7754 pub fn parent(vi: Value.Index, isel: *Select) Parent {
7562 const value = vi.get(isel);7755 const value = vi.get(isel);
7563 return switch (value.flags.parent_tag) {7756 return switch (value.flags.parent_tag) {
...@@ -8070,123 +8263,7 @@ pub const Value = struct {...@@ -8070,123 +8263,7 @@ pub const Value = struct {
8070 }),8263 }),
8071 64 => {},8264 64 => {},
8072 };8265 };
8073 try isel.emit(emit: switch (part_size) {8266 try isel.loadReg(part_ra, part_size, part_vi.signedness(isel), base_ra, opts.offset);
8074 else => return isel.fail("bad load size of {d}", .{part_size}),
8075 1 => if (part_is_vector) .ldr(part_ra.b(), .{ .unsigned_offset = .{
8076 .base = base_ra.x(),
8077 .offset = @intCast(opts.offset),
8078 } }) else switch (part_vi.signedness(isel)) {
8079 .signed => .ldrsb(part_ra.w(), .{ .unsigned_offset = .{
8080 .base = base_ra.x(),
8081 .offset = @intCast(opts.offset),
8082 } }),
8083 .unsigned => .ldrb(part_ra.w(), .{ .unsigned_offset = .{
8084 .base = base_ra.x(),
8085 .offset = @intCast(opts.offset),
8086 } }),
8087 },
8088 2 => if (part_is_vector) .ldr(part_ra.h(), .{ .unsigned_offset = .{
8089 .base = base_ra.x(),
8090 .offset = @intCast(opts.offset),
8091 } }) else switch (part_vi.signedness(isel)) {
8092 .signed => .ldrsh(part_ra.w(), .{ .unsigned_offset = .{
8093 .base = base_ra.x(),
8094 .offset = @intCast(opts.offset),
8095 } }),
8096 .unsigned => .ldrh(part_ra.w(), .{ .unsigned_offset = .{
8097 .base = base_ra.x(),
8098 .offset = @intCast(opts.offset),
8099 } }),
8100 },
8101 3 => {
8102 const lo16_ra = try isel.allocIntReg();
8103 defer isel.freeReg(lo16_ra);
8104 try isel.emit(.orr(part_ra.w(), lo16_ra.w(), .{ .shifted_register = .{
8105 .register = part_ra.w(),
8106 .shift = .{ .lsl = 16 },
8107 } }));
8108 try isel.emit(switch (part_vi.signedness(isel)) {
8109 .signed => .ldrsb(part_ra.w(), .{ .unsigned_offset = .{
8110 .base = base_ra.x(),
8111 .offset = @intCast(opts.offset + 2),
8112 } }),
8113 .unsigned => .ldrb(part_ra.w(), .{ .unsigned_offset = .{
8114 .base = base_ra.x(),
8115 .offset = @intCast(opts.offset + 2),
8116 } }),
8117 });
8118 break :emit .ldrh(lo16_ra.w(), .{ .unsigned_offset = .{
8119 .base = base_ra.x(),
8120 .offset = @intCast(opts.offset),
8121 } });
8122 },
8123 4 => .ldr(if (part_is_vector) part_ra.s() else part_ra.w(), .{ .unsigned_offset = .{
8124 .base = base_ra.x(),
8125 .offset = @intCast(opts.offset),
8126 } }),
8127 5 => {
8128 const lo32_ra = try isel.allocIntReg();
8129 defer isel.freeReg(lo32_ra);
8130 try isel.emit(.orr(part_ra.x(), lo32_ra.x(), .{ .shifted_register = .{
8131 .register = part_ra.x(),
8132 .shift = .{ .lsl = 32 },
8133 } }));
8134 try isel.emit(switch (part_vi.signedness(isel)) {
8135 .signed => .ldrsb(part_ra.w(), .{ .unsigned_offset = .{
8136 .base = base_ra.x(),
8137 .offset = @intCast(opts.offset + 4),
8138 } }),
8139 .unsigned => .ldrb(part_ra.w(), .{ .unsigned_offset = .{
8140 .base = base_ra.x(),
8141 .offset = @intCast(opts.offset + 4),
8142 } }),
8143 });
8144 break :emit .ldr(lo32_ra.w(), .{ .unsigned_offset = .{
8145 .base = base_ra.x(),
8146 .offset = @intCast(opts.offset),
8147 } });
8148 },
8149 7 => {
8150 const lo32_ra = try isel.allocIntReg();
8151 defer isel.freeReg(lo32_ra);
8152 const lo48_ra = try isel.allocIntReg();
8153 defer isel.freeReg(lo48_ra);
8154 try isel.emit(.orr(part_ra.x(), lo48_ra.x(), .{ .shifted_register = .{
8155 .register = part_ra.x(),
8156 .shift = .{ .lsl = 32 + 16 },
8157 } }));
8158 try isel.emit(switch (part_vi.signedness(isel)) {
8159 .signed => .ldrsb(part_ra.w(), .{ .unsigned_offset = .{
8160 .base = base_ra.x(),
8161 .offset = @intCast(opts.offset + 4 + 2),
8162 } }),
8163 .unsigned => .ldrb(part_ra.w(), .{ .unsigned_offset = .{
8164 .base = base_ra.x(),
8165 .offset = @intCast(opts.offset + 4 + 2),
8166 } }),
8167 });
8168 try isel.emit(.orr(lo48_ra.x(), lo32_ra.x(), .{ .shifted_register = .{
8169 .register = lo48_ra.x(),
8170 .shift = .{ .lsl = 32 },
8171 } }));
8172 try isel.emit(.ldrh(lo48_ra.w(), .{ .unsigned_offset = .{
8173 .base = base_ra.x(),
8174 .offset = @intCast(opts.offset + 4),
8175 } }));
8176 break :emit .ldr(lo32_ra.w(), .{ .unsigned_offset = .{
8177 .base = base_ra.x(),
8178 .offset = @intCast(opts.offset),
8179 } });
8180 },
8181 8 => .ldr(if (part_is_vector) part_ra.d() else part_ra.x(), .{ .unsigned_offset = .{
8182 .base = base_ra.x(),
8183 .offset = @intCast(opts.offset),
8184 } }),
8185 16 => .ldr(part_ra.q(), .{ .unsigned_offset = .{
8186 .base = base_ra.x(),
8187 .offset = @intCast(opts.offset),
8188 } }),
8189 });
8190 if (part_ra != .zr) {8267 if (part_ra != .zr) {
8191 const live_vi = isel.live_registers.getPtr(part_ra);8268 const live_vi = isel.live_registers.getPtr(part_ra);
8192 assert(live_vi.* == .allocating);8269 assert(live_vi.* == .allocating);
...@@ -9104,7 +9181,7 @@ pub const Value = struct {...@@ -9104,7 +9181,7 @@ pub const Value = struct {
9104 const live_vi = isel.live_registers.getPtr(mat.ra);9181 const live_vi = isel.live_registers.getPtr(mat.ra);
9105 assert(live_vi.* == .allocating);9182 assert(live_vi.* == .allocating);
9106 var vi = mat.vi;9183 var vi = mat.vi;
9107 var offset: i65 = 0;9184 var offset: u64 = 0;
9108 const size = mat.vi.size(isel);9185 const size = mat.vi.size(isel);
9109 free: while (true) {9186 free: while (true) {
9110 if (vi.register(isel)) |ra| {9187 if (vi.register(isel)) |ra| {
...@@ -9156,93 +9233,16 @@ pub const Value = struct {...@@ -9156,93 +9233,16 @@ pub const Value = struct {
9156 live_vi.* = mat.vi;9233 live_vi.* = mat.vi;
9157 return;9234 return;
9158 },9235 },
9159 .stack_slot => |stack_slot| {9236 .stack_slot => |stack_slot| break :free try isel.loadReg(
9160 offset += stack_slot.offset;9237 mat.ra,
9161 break :free try isel.emit(switch (size) {9238 size,
9162 else => unreachable,9239 mat.vi.signedness(isel),
9163 1 => if (mat.ra.isVector()) .ldr(mat.ra.b(), .{ .unsigned_offset = .{9240 stack_slot.base,
9164 .base = stack_slot.base.x(),9241 @as(i65, stack_slot.offset) + offset,
9165 .offset = @intCast(offset),9242 ),
9166 } }) else switch (mat.vi.signedness(isel)) {
9167 .signed => .ldrsb(mat.ra.w(), .{ .unsigned_offset = .{
9168 .base = stack_slot.base.x(),
9169 .offset = @intCast(offset),
9170 } }),
9171 .unsigned => .ldrb(mat.ra.w(), .{ .unsigned_offset = .{
9172 .base = stack_slot.base.x(),
9173 .offset = @intCast(offset),
9174 } }),
9175 },
9176 2 => if (mat.ra.isVector()) .ldr(mat.ra.h(), .{ .unsigned_offset = .{
9177 .base = stack_slot.base.x(),
9178 .offset = @intCast(offset),
9179 } }) else switch (mat.vi.signedness(isel)) {
9180 .signed => .ldrsh(mat.ra.w(), .{ .unsigned_offset = .{
9181 .base = stack_slot.base.x(),
9182 .offset = @intCast(offset),
9183 } }),
9184 .unsigned => .ldrh(mat.ra.w(), .{ .unsigned_offset = .{
9185 .base = stack_slot.base.x(),
9186 .offset = @intCast(offset),
9187 } }),
9188 },
9189 4 => .ldr(if (mat.ra.isVector()) mat.ra.s() else mat.ra.w(), .{ .unsigned_offset = .{
9190 .base = stack_slot.base.x(),
9191 .offset = @intCast(offset),
9192 } }),
9193 8 => .ldr(if (mat.ra.isVector()) mat.ra.d() else mat.ra.x(), .{ .unsigned_offset = .{
9194 .base = stack_slot.base.x(),
9195 .offset = @intCast(offset),
9196 } }),
9197 16 => .ldr(mat.ra.q(), .{ .unsigned_offset = .{
9198 .base = stack_slot.base.x(),
9199 .offset = @intCast(offset),
9200 } }),
9201 });
9202 },
9203 .address => |base_vi| {9243 .address => |base_vi| {
9204 const base_mat = try base_vi.matReg(isel);9244 const base_mat = try base_vi.matReg(isel);
9205 try isel.emit(switch (size) {9245 try isel.loadReg(mat.ra, size, mat.vi.signedness(isel), base_mat.ra, offset);
9206 else => unreachable,
9207 1 => if (mat.ra.isVector()) .ldr(mat.ra.b(), .{ .unsigned_offset = .{
9208 .base = base_mat.ra.x(),
9209 .offset = @intCast(offset),
9210 } }) else switch (mat.vi.signedness(isel)) {
9211 .signed => .ldrsb(mat.ra.w(), .{ .unsigned_offset = .{
9212 .base = base_mat.ra.x(),
9213 .offset = @intCast(offset),
9214 } }),
9215 .unsigned => .ldrb(mat.ra.w(), .{ .unsigned_offset = .{
9216 .base = base_mat.ra.x(),
9217 .offset = @intCast(offset),
9218 } }),
9219 },
9220 2 => if (mat.ra.isVector()) .ldr(mat.ra.h(), .{ .unsigned_offset = .{
9221 .base = base_mat.ra.x(),
9222 .offset = @intCast(offset),
9223 } }) else switch (mat.vi.signedness(isel)) {
9224 .signed => .ldrsh(mat.ra.w(), .{ .unsigned_offset = .{
9225 .base = base_mat.ra.x(),
9226 .offset = @intCast(offset),
9227 } }),
9228 .unsigned => .ldrh(mat.ra.w(), .{ .unsigned_offset = .{
9229 .base = base_mat.ra.x(),
9230 .offset = @intCast(offset),
9231 } }),
9232 },
9233 4 => .ldr(if (mat.ra.isVector()) mat.ra.s() else mat.ra.w(), .{ .unsigned_offset = .{
9234 .base = base_mat.ra.x(),
9235 .offset = @intCast(offset),
9236 } }),
9237 8 => .ldr(if (mat.ra.isVector()) mat.ra.d() else mat.ra.x(), .{ .unsigned_offset = .{
9238 .base = base_mat.ra.x(),
9239 .offset = @intCast(offset),
9240 } }),
9241 16 => .ldr(mat.ra.q(), .{ .unsigned_offset = .{
9242 .base = base_mat.ra.x(),
9243 .offset = @intCast(offset),
9244 } }),
9245 });
9246 break :free try base_mat.finish(isel);9246 break :free try base_mat.finish(isel);
9247 },9247 },
9248 .value => |parent_vi| vi = parent_vi,9248 .value => |parent_vi| vi = parent_vi,
src/codegen/aarch64/encoding.zig+434-41
...@@ -1072,7 +1072,7 @@ pub const Register = struct {...@@ -1072,7 +1072,7 @@ pub const Register = struct {
1072 }1072 }
10731073
1074 pub fn parse(reg: []const u8) ?Register {1074 pub fn parse(reg: []const u8) ?Register {
1075 return if (reg.len == 0) null else switch (reg[0]) {1075 return if (reg.len == 0) null else switch (std.ascii.toLower(reg[0])) {
1076 else => null,1076 else => null,
1077 'r' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| switch (n) {1077 'r' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| switch (n) {
1078 0...30 => .{1078 0...30 => .{
...@@ -1087,27 +1087,27 @@ pub const Register = struct {...@@ -1087,27 +1087,27 @@ pub const Register = struct {
1087 .format = .{ .integer = .doubleword },1087 .format = .{ .integer = .doubleword },
1088 },1088 },
1089 31 => null,1089 31 => null,
1090 } else |_| if (std.mem.eql(u8, reg, "xzr")) .xzr else null,1090 } else |_| if (toLowerEqlAssertLower(reg, "xzr")) .xzr else null,
1091 'w' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| switch (n) {1091 'w' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| switch (n) {
1092 0...30 => .{1092 0...30 => .{
1093 .alias = @enumFromInt(@intFromEnum(Alias.r0) + n),1093 .alias = @enumFromInt(@intFromEnum(Alias.r0) + n),
1094 .format = .{ .integer = .word },1094 .format = .{ .integer = .word },
1095 },1095 },
1096 31 => null,1096 31 => null,
1097 } else |_| if (std.mem.eql(u8, reg, "wzr"))1097 } else |_| if (toLowerEqlAssertLower(reg, "wzr"))
1098 .wzr1098 .wzr
1099 else if (std.mem.eql(u8, reg, "wsp"))1099 else if (toLowerEqlAssertLower(reg, "wsp"))
1100 .wsp1100 .wsp
1101 else1101 else
1102 null,1102 null,
1103 'i' => return if (std.mem.eql(u8, reg, "ip") or std.mem.eql(u8, reg, "ip0"))1103 'i' => return if (toLowerEqlAssertLower(reg, "ip") or toLowerEqlAssertLower(reg, "ip0"))
1104 .ip01104 .ip0
1105 else if (std.mem.eql(u8, reg, "ip1"))1105 else if (toLowerEqlAssertLower(reg, "ip1"))
1106 .ip11106 .ip1
1107 else1107 else
1108 null,1108 null,
1109 'f' => return if (std.mem.eql(u8, reg, "fp")) .fp else null,1109 'f' => return if (toLowerEqlAssertLower(reg, "fp")) .fp else null,
1110 'p' => return if (std.mem.eql(u8, reg, "pc")) .pc else null,1110 'p' => return if (toLowerEqlAssertLower(reg, "pc")) .pc else null,
1111 'v' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{1111 'v' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
1112 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),1112 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
1113 .format = .alias,1113 .format = .alias,
...@@ -1123,7 +1123,7 @@ pub const Register = struct {...@@ -1123,7 +1123,7 @@ pub const Register = struct {
1123 's' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{1123 's' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
1124 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),1124 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
1125 .format = .{ .scalar = .single },1125 .format = .{ .scalar = .single },
1126 } else |_| if (std.mem.eql(u8, reg, "sp")) .sp else null,1126 } else |_| if (toLowerEqlAssertLower(reg, "sp")) .sp else null,
1127 'h' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{1127 'h' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
1128 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),1128 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
1129 .format = .{ .scalar = .half },1129 .format = .{ .scalar = .half },
...@@ -1141,6 +1141,422 @@ pub const Register = struct {...@@ -1141,6 +1141,422 @@ pub const Register = struct {
1141 pub fn fmtCase(reg: Register, case: aarch64.Disassemble.Case) aarch64.Disassemble.RegisterFormatter {1141 pub fn fmtCase(reg: Register, case: aarch64.Disassemble.Case) aarch64.Disassemble.RegisterFormatter {
1142 return .{ .reg = reg, .case = case };1142 return .{ .reg = reg, .case = case };
1143 }1143 }
1144
1145 pub const System = packed struct(u16) {
1146 op2: u3,
1147 CRm: u4,
1148 CRn: u4,
1149 op1: u3,
1150 op0: u2,
1151
1152 // D19.2 General system control registers
1153 /// D19.2.1 ACCDATA_EL1, Accelerator Data
1154 pub const accdata_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b101 };
1155 /// D19.2.2 ACTLR_EL1, Auxiliary Control Register (EL1)
1156 pub const actlr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b001 };
1157 /// D19.2.3 ACTLR_EL2, Auxiliary Control Register (EL2)
1158 pub const actlr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b001 };
1159 /// D19.2.4 ACTLR_EL3, Auxiliary Control Register (EL3)
1160 pub const actlr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b001 };
1161 /// D19.2.5 AFSR0_EL1, Auxiliary Fault Status Register 0 (EL1)
1162 pub const afsr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b000 };
1163 /// D19.2.5 AFSR0_EL12, Auxiliary Fault Status Register 0 (EL12)
1164 pub const afsr0_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b000 };
1165 /// D19.2.6 AFSR0_EL2, Auxiliary Fault Status Register 0 (EL2)
1166 pub const afsr0_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b000 };
1167 /// D19.2.7 AFSR0_EL3, Auxiliary Fault Status Register 0 (EL3)
1168 pub const afsr0_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b000 };
1169 /// D19.2.8 AFSR1_EL1, Auxiliary Fault Status Register 1 (EL1)
1170 pub const afsr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b001 };
1171 /// D19.2.8 AFSR1_EL12, Auxiliary Fault Status Register 1 (EL12)
1172 pub const afsr1_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b001 };
1173 /// D19.2.9 AFSR1_EL2, Auxiliary Fault Status Register 1 (EL2)
1174 pub const afsr1_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b001 };
1175 /// D19.2.10 AFSR1_EL3, Auxiliary Fault Status Register 1 (EL3)
1176 pub const afsr1_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b001 };
1177 /// D19.2.11 AIDR_EL1, Auxiliary ID Register
1178 pub const aidr_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b111 };
1179 /// D19.2.12 AMAIR_EL1, Auxiliary Memory Attribute Indirection Register (EL1)
1180 pub const amair_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0011, .op2 = 0b000 };
1181 /// D19.2.12 AMAIR_EL12, Auxiliary Memory Attribute Indirection Register (EL12)
1182 pub const amair_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1010, .CRm = 0b0011, .op2 = 0b000 };
1183 /// D19.2.13 AMAIR_EL2, Auxiliary Memory Attribute Indirection Register (EL2)
1184 pub const amair_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1010, .CRm = 0b0011, .op2 = 0b000 };
1185 /// D19.2.14 AMAIR_EL3, Auxiliary Memory Attribute Indirection Register (EL3)
1186 pub const amair_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1010, .CRm = 0b0011, .op2 = 0b000 };
1187 /// D19.2.15 APDAKeyHi_EL1, Pointer Authentication Key A for Data (bits[127:64])
1188 pub const apdakeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b001 };
1189 /// D19.2.16 APDAKeyLo_EL1, Pointer Authentication Key A for Data (bits[63:0])
1190 pub const apdakeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b000 };
1191 /// D19.2.17 APDBKeyHi_EL1, Pointer Authentication Key B for Data (bits[127:64])
1192 pub const apdbkeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b011 };
1193 /// D19.2.18 APDAKeyHi_EL1, Pointer Authentication Key B for Data (bits[63:0])
1194 pub const apdbkeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b010 };
1195 /// D19.2.19 APGAKeyHi_EL1, Pointer Authentication Key A for Code (bits[127:64])
1196 pub const apgakeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0011, .op2 = 0b001 };
1197 /// D19.2.20 APGAKeyLo_EL1, Pointer Authentication Key A for Code (bits[63:0])
1198 pub const apgakeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0011, .op2 = 0b000 };
1199 /// D19.2.21 APIAKeyHi_EL1, Pointer Authentication Key A for Instruction (bits[127:64])
1200 pub const apiakeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b001 };
1201 /// D19.2.22 APIAKeyLo_EL1, Pointer Authentication Key A for Instruction (bits[63:0])
1202 pub const apiakeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b000 };
1203 /// D19.2.23 APIBKeyHi_EL1, Pointer Authentication Key B for Instruction (bits[127:64])
1204 pub const apibkeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b011 };
1205 /// D19.2.24 APIBKeyLo_EL1, Pointer Authentication Key B for Instruction (bits[63:0])
1206 pub const apibkeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b010 };
1207 /// D19.2.25 CCSIDR2_EL1, Current Cache Size ID Register 2
1208 pub const ccsidr2_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b010 };
1209 /// D19.2.26 CCSIDR_EL1, Current Cache Size ID Register
1210 pub const ccsidr_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b000 };
1211 /// D19.2.27 CLIDR_EL1, Cache Level ID Register
1212 pub const clidr_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b001 };
1213 /// D19.2.28 CONTEXTIDR_EL1, Context ID Register (EL1)
1214 pub const contextidr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b001 };
1215 /// D19.2.28 CONTEXTIDR_EL12, Context ID Register (EL12)
1216 pub const contextidr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b001 };
1217 /// D19.2.29 CONTEXTIDR_EL2, Context ID Register (EL2)
1218 pub const contextidr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b001 };
1219 /// D19.2.30 CPACR_EL1, Architectural Feature Access Control Register
1220 pub const cpacr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b010 };
1221 /// D19.2.30 CPACR_EL12, Architectural Feature Access Control Register
1222 pub const cpacr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b010 };
1223 /// D19.2.31 CPACR_EL2, Architectural Feature Trap Register (EL2)
1224 pub const cptr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b010 };
1225 /// D19.2.32 CPACR_EL3, Architectural Feature Trap Register (EL3)
1226 pub const cptr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b010 };
1227 /// D19.2.33 CSSELR_EL1, Cache Size Selection Register
1228 pub const csselr_el1: System = .{ .op0 = 0b11, .op1 = 0b010, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b000 };
1229 /// D19.2.34 CTR_EL0, Cache Type Register
1230 pub const ctr_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b001 };
1231 /// D19.2.35 DACR32_EL2, Domain Access Control Register
1232 pub const dacr32_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0011, .CRm = 0b0000, .op2 = 0b000 };
1233 /// D19.2.36 DCZID_EL0, Data Cache Zero ID Register
1234 pub const dczid_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b111 };
1235 /// D19.2.37 ESR_EL1, Exception Syndrome Register (EL1)
1236 pub const esr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0010, .op2 = 0b000 };
1237 /// D19.2.37 ESR_EL12, Exception Syndrome Register (EL12)
1238 pub const esr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0101, .CRm = 0b0010, .op2 = 0b000 };
1239 /// D19.2.38 ESR_EL2, Exception Syndrome Register (EL2)
1240 pub const esr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0010, .op2 = 0b000 };
1241 /// D19.2.39 ESR_EL3, Exception Syndrome Register (EL3)
1242 pub const esr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0101, .CRm = 0b0010, .op2 = 0b000 };
1243 /// D19.2.40 FAR_EL1, Fault Address Register (EL1)
1244 pub const far_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b000 };
1245 /// D19.2.40 FAR_EL12, Fault Address Register (EL12)
1246 pub const far_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b000 };
1247 /// D19.2.41 FAR_EL2, Fault Address Register (EL2)
1248 pub const far_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b000 };
1249 /// D19.2.42 FAR_EL3, Fault Address Register (EL3)
1250 pub const far_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b000 };
1251 /// D19.2.43 FPEXC32_EL2, Floating-Point Exception Control Register
1252 pub const fpexc32_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0011, .op2 = 0b000 };
1253 /// D19.2.44 GCR_EL1, Tag Control Register
1254 pub const gcr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b110 };
1255 /// D19.2.45 GMID_EL1, Tag Control Register
1256 pub const gmid_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b100 };
1257 /// D19.2.46 HACR_EL2, Hypervisor Auxiliary Control Register
1258 pub const hacr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b111 };
1259 /// D19.2.47 HAFGRTR_EL2, Hypervisor Activity Monitors Fine-Grained Read Trap Register
1260 pub const hafgrtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0011, .CRm = 0b0001, .op2 = 0b110 };
1261 /// D19.2.48 HCR_EL2, Hypervisor Configuration Register
1262 pub const hcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b000 };
1263 /// D19.2.49 HCRX_EL2, Extended Hypervisor Configuration Register
1264 pub const hcrx_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b010 };
1265 /// D19.2.50 HDFGRTR_EL2, Hypervisor Debug Fine-Grained Read Trap Register
1266 pub const hdfgrtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0011, .CRm = 0b0001, .op2 = 0b100 };
1267 /// D19.2.51 HDFGWTR_EL2, Hypervisor Debug Fine-Grained Write Trap Register
1268 pub const hdfgwtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0011, .CRm = 0b0001, .op2 = 0b101 };
1269 /// D19.2.52 HFGITR_EL2, Hypervisor Fine-Grained Instruction Trap Register
1270 pub const hfgitr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b110 };
1271 /// D19.2.53 HFGRTR_EL2, Hypervisor Fine-Grained Read Trap Register
1272 pub const hfgrtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b100 };
1273 /// D19.2.54 HFGWTR_EL2, Hypervisor Fine-Grained Write Trap Register
1274 pub const hfgwtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b101 };
1275 /// D19.2.55 HPFAR_EL2, Hypervisor IPA Fault Address Register
1276 pub const hpfar_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b100 };
1277 /// D19.2.56 HSTR_EL2, Hypervisor System Trap Register
1278 pub const hstr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b011 };
1279 /// D19.2.57 ID_AA64AFR0_EL1, AArch64 Auxiliary Feature Register 0
1280 pub const id_aa64afr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0101, .op2 = 0b100 };
1281 /// D19.2.58 ID_AA64AFR1_EL1, AArch64 Auxiliary Feature Register 1
1282 pub const id_aa64afr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0101, .op2 = 0b101 };
1283 /// D19.2.59 ID_AA64DFR0_EL1, AArch64 Debug Feature Register 0
1284 pub const id_aa64dfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0101, .op2 = 0b000 };
1285 /// D19.2.60 ID_AA64DFR1_EL1, AArch64 Debug Feature Register 1
1286 pub const id_aa64dfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0101, .op2 = 0b001 };
1287 /// D19.2.61 ID_AA64ISAR0_EL1, AArch64 Instruction Set Attribute Register 0
1288 pub const id_aa64isar0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0110, .op2 = 0b000 };
1289 /// D19.2.62 ID_AA64ISAR1_EL1, AArch64 Instruction Set Attribute Register 1
1290 pub const id_aa64isar1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0110, .op2 = 0b001 };
1291 /// D19.2.63 ID_AA64ISAR2_EL1, AArch64 Instruction Set Attribute Register 2
1292 pub const id_aa64isar2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0110, .op2 = 0b010 };
1293 /// D19.2.64 ID_AA64MMFR0_EL1, AArch64 Memory Model Feature Register 0
1294 pub const id_aa64mmfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b000 };
1295 /// D19.2.65 ID_AA64MMFR1_EL1, AArch64 Memory Model Feature Register 1
1296 pub const id_aa64mmfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b001 };
1297 /// D19.2.66 ID_AA64MMFR2_EL1, AArch64 Memory Model Feature Register 2
1298 pub const id_aa64mmfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b010 };
1299 /// D19.2.67 ID_AA64MMFR3_EL1, AArch64 Memory Model Feature Register 3
1300 pub const id_aa64mmfr3_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b011 };
1301 /// D19.2.68 ID_AA64MMFR4_EL1, AArch64 Memory Model Feature Register 4
1302 pub const id_aa64mmfr4_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b100 };
1303 /// D19.2.69 ID_AA64PFR0_EL1, AArch64 Processor Feature Register 0
1304 pub const id_aa64pfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b000 };
1305 /// D19.2.70 ID_AA64PFR1_EL1, AArch64 Processor Feature Register 1
1306 pub const id_aa64pfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b001 };
1307 /// D19.2.71 ID_AA64PFR2_EL1, AArch64 Processor Feature Register 2
1308 pub const id_aa64pfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b010 };
1309 /// D19.2.72 ID_AA64SMFR0_EL1, SME Feature ID Register 0
1310 pub const id_aa64smfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b101 };
1311 /// D19.2.73 ID_AA64ZFR0_EL1, SVE Feature ID Register 0
1312 pub const id_aa64zfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b100 };
1313 /// D19.2.74 ID_AFR0_EL1, AArch32 Auxiliary Feature Register 0
1314 pub const id_afr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b011 };
1315 /// D19.2.75 ID_DFR0_EL1, AArch32 Debug Feature Register 0
1316 pub const id_dfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b010 };
1317 /// D19.2.76 ID_DFR1_EL1, AArch32 Debug Feature Register 1
1318 pub const id_dfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b101 };
1319 /// D19.2.77 ID_ISAR0_EL1, AArch32 Instruction Set Attribute Register 0
1320 pub const id_isar0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b000 };
1321 /// D19.2.78 ID_ISAR1_EL1, AArch32 Instruction Set Attribute Register 1
1322 pub const id_isar1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b001 };
1323 /// D19.2.79 ID_ISAR2_EL1, AArch32 Instruction Set Attribute Register 2
1324 pub const id_isar2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b010 };
1325 /// D19.2.80 ID_ISAR3_EL1, AArch32 Instruction Set Attribute Register 3
1326 pub const id_isar3_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b011 };
1327 /// D19.2.81 ID_ISAR4_EL1, AArch32 Instruction Set Attribute Register 4
1328 pub const id_isar4_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b100 };
1329 /// D19.2.82 ID_ISAR5_EL1, AArch32 Instruction Set Attribute Register 5
1330 pub const id_isar5_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b101 };
1331 /// D19.2.83 ID_ISAR6_EL1, AArch32 Instruction Set Attribute Register 6
1332 pub const id_isar6_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b111 };
1333 /// D19.2.84 ID_MMFR0_EL1, AArch32 Memory Model Feature Register 0
1334 pub const id_mmfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b100 };
1335 /// D19.2.85 ID_MMFR1_EL1, AArch32 Memory Model Feature Register 1
1336 pub const id_mmfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b101 };
1337 /// D19.2.86 ID_MMFR2_EL1, AArch32 Memory Model Feature Register 2
1338 pub const id_mmfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b110 };
1339 /// D19.2.87 ID_MMFR3_EL1, AArch32 Memory Model Feature Register 3
1340 pub const id_mmfr3_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b111 };
1341 /// D19.2.88 ID_MMFR4_EL1, AArch32 Memory Model Feature Register 4
1342 pub const id_mmfr4_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b110 };
1343 /// D19.2.89 ID_MMFR5_EL1, AArch32 Memory Model Feature Register 5
1344 pub const id_mmfr5_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b110 };
1345 /// D19.2.90 ID_PFR0_EL1, AArch32 Processor Feature Register 0
1346 pub const id_pfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b000 };
1347 /// D19.2.91 ID_PFR1_EL1, AArch32 Processor Feature Register 1
1348 pub const id_pfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b001 };
1349 /// D19.2.92 ID_PFR2_EL1, AArch32 Processor Feature Register 2
1350 pub const id_pfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b100 };
1351 /// D19.2.93 IFSR32_EL2, Instruction Fault Status Register (EL2)
1352 pub const ifsr32_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0000, .op2 = 0b001 };
1353 /// D19.2.94 ISR_EL1, Interrupt Status Register
1354 pub const isr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1100, .CRm = 0b0001, .op2 = 0b000 };
1355 /// D19.2.95 LORC_EL1, LORegion Control (EL1)
1356 pub const lorc_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b011 };
1357 /// D19.2.96 LOREA_EL1, LORegion End Address (EL1)
1358 pub const lorea_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b001 };
1359 /// D19.2.97 SORID_EL1, LORegionID (EL1)
1360 pub const lorid_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b111 };
1361 /// D19.2.98 LORN_EL1, LORegion Number (EL1)
1362 pub const lorn_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b010 };
1363 /// D19.2.99 LORSA_EL1, LORegion Start Address (EL1)
1364 pub const lorsa_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b000 };
1365 /// D19.2.100 MAIR_EL1, Memory Attribute Indirection Register (EL1)
1366 pub const mair_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0010, .op2 = 0b000 };
1367 /// D19.2.100 MAIR_EL12, Memory Attribute Indirection Register (EL12)
1368 pub const mair_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1010, .CRm = 0b0010, .op2 = 0b000 };
1369 /// D19.2.101 MAIR_EL2, Memory Attribute Indirection Register (EL2)
1370 pub const mair_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1010, .CRm = 0b0010, .op2 = 0b000 };
1371 /// D19.2.102 MAIR_EL3, Memory Attribute Indirection Register (EL3)
1372 pub const mair_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1010, .CRm = 0b0010, .op2 = 0b000 };
1373 /// D19.2.103 MIDR_EL1, Main ID Register
1374 pub const midr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b000 };
1375 /// D19.2.104 MPIDR_EL1, Multiprocessor Affinity Register
1376 pub const mpidr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b101 };
1377 /// D19.2.105 MVFR0_EL1, AArch32 Media and VFP Feature Register 0
1378 pub const mvfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b000 };
1379 /// D19.2.106 MVFR1_EL1, AArch32 Media and VFP Feature Register 1
1380 pub const mvfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b001 };
1381 /// D19.2.107 MVFR2_EL1, AArch32 Media and VFP Feature Register 2
1382 pub const mvfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b010 };
1383 /// D19.2.108 PAR_EL1, Physical Address Register
1384 pub const par_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0111, .CRm = 0b0100, .op2 = 0b000 };
1385 /// D19.2.109 REVIDR_EL1, Revision ID Register
1386 pub const revidr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b110 };
1387 /// D19.2.110 RGSR_EL1, Random Allocation Tag Seed Register
1388 pub const rgsr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b101 };
1389 /// D19.2.111 RMR_EL1, Reset Management Register (EL1)
1390 pub const rmr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b010 };
1391 /// D19.2.112 RMR_EL2, Reset Management Register (EL2)
1392 pub const rmr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b010 };
1393 /// D19.2.113 RMR_EL3, Reset Management Register (EL3)
1394 pub const rmr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b010 };
1395 /// D19.2.114 RNDR, Random Number
1396 pub const rndr: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b0010, .CRm = 0b0100, .op2 = 0b000 };
1397 /// D19.2.115 RNDRRS, Reseeded Random Number
1398 pub const rndrrs: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b0010, .CRm = 0b0100, .op2 = 0b001 };
1399 /// D19.2.116 RVBAR_EL1, Reset Vector Base Address Register (if EL2 and EL3 not implemented)
1400 pub const rvbar_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b001 };
1401 /// D19.2.117 RVBAR_EL2, Reset Vector Base Address Register (if EL3 not implemented)
1402 pub const rvbar_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b001 };
1403 /// D19.2.118 RVBAR_EL3, Reset Vector Base Address Register (if EL3 implemented)
1404 pub const rvbar_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b001 };
1405 /// D19.2.120 SCR_EL3, Secure Configuration Register
1406 pub const scr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b000 };
1407 /// D19.2.121 SCTLR2_EL1, System Control Register (EL1)
1408 pub const sctlr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b011 };
1409 /// D19.2.121 SCTLR2_EL12, System Control Register (EL12)
1410 pub const sctlr2_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b011 };
1411 /// D19.2.122 SCTLR2_EL2, System Control Register (EL2)
1412 pub const sctlr2_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b011 };
1413 /// D19.2.123 SCTLR2_EL3, System Control Register (EL3)
1414 pub const sctlr2_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b011 };
1415 /// D19.2.124 SCTLR_EL1, System Control Register (EL1)
1416 pub const sctlr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b000 };
1417 /// D19.2.124 SCTLR_EL12, System Control Register (EL12)
1418 pub const sctlr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b000 };
1419 /// D19.2.125 SCTLR_EL2, System Control Register (EL2)
1420 pub const sctlr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b000 };
1421 /// D19.2.126 SCTLR_EL3, System Control Register (EL3)
1422 pub const sctlr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b000 };
1423 /// D19.2.127 SCXTNUM_EL0, EL0 Read/Write Software Context Number
1424 pub const scxtnum_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
1425 /// D19.2.128 SCXTNUM_EL1, EL1 Read/Write Software Context Number
1426 pub const scxtnum_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
1427 /// D19.2.128 SCXTNUM_EL12, EL12 Read/Write Software Context Number
1428 pub const scxtnum_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
1429 /// D19.2.129 SCXTNUM_EL2, EL2 Read/Write Software Context Number
1430 pub const scxtnum_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
1431 /// D19.2.130 SCXTNUM_EL3, EL3 Read/Write Software Context Number
1432 pub const scxtnum_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
1433 /// D19.2.131 SMCR_EL1, SME Control Register (EL1)
1434 pub const smcr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b110 };
1435 /// D19.2.131 SMCR_EL12, SME Control Register (EL12)
1436 pub const smcr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b110 };
1437 /// D19.2.132 SMCR_EL2, SME Control Register (EL2)
1438 pub const smcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b110 };
1439 /// D19.2.133 SMCR_EL3, SME Control Register (EL3)
1440 pub const smcr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b110 };
1441 /// D19.2.134 SMIDR_EL1, Streaming Mode Identification Register
1442 pub const smidr_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b110 };
1443 /// D19.2.135 SMPRIMAP_EL2, Streaming Mode Priority Mapping Register
1444 pub const smprimap_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b101 };
1445 /// D19.2.136 SMPRI_EL1, Streaming Mode Priority Register
1446 pub const smpri_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b100 };
1447 /// D19.2.137 TCR2_EL1, Extended Translation Control Register (EL1)
1448 pub const tcr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b011 };
1449 /// D19.2.137 TCR2_EL12, Extended Translation Control Register (EL12)
1450 pub const tcr2_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b011 };
1451 /// D19.2.138 TCR2_EL2, Extended Translation Control Register (EL2)
1452 pub const tcr2_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b011 };
1453 /// D19.2.139 TCR_EL1, Translation Control Register (EL1)
1454 pub const tcr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b010 };
1455 /// D19.2.139 TCR_EL12, Translation Control Register (EL12)
1456 pub const tcr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b010 };
1457 /// D19.2.140 TCR_EL2, Translation Control Register (EL2)
1458 pub const tcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b010 };
1459 /// D19.2.141 TCR_EL3, Translation Control Register (EL3)
1460 pub const tcr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b010 };
1461 /// D19.2.142 TFSRE0_EL1, Tag Fault Status Register (EL0)
1462 pub const tfsre0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b001 };
1463 /// D19.2.143 TFSR_EL1, Tag Fault Status Register (EL1)
1464 pub const tfsr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b000 };
1465 /// D19.2.143 TFSR_EL12, Tag Fault Status Register (EL12)
1466 pub const tfsr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b000 };
1467 /// D19.2.144 TFSR_EL2, Tag Fault Status Register (EL2)
1468 pub const tfsr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b000 };
1469 /// D19.2.145 TFSR_EL3, Tag Fault Status Register (EL3)
1470 pub const tfsr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b000 };
1471 /// D19.2.146 TPIDR2_EL0, EL0 Read/Write Software Thread ID Register 2
1472 pub const tpidr2_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b101 };
1473 /// D19.2.147 TPIDR_EL0, EL0 Read/Write Software Thread ID Register
1474 pub const tpidr_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b010 };
1475 /// D19.2.148 TPIDR_EL1, EL1 Read/Write Software Thread ID Register
1476 pub const tpidr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b100 };
1477 /// D19.2.149 TPIDR_EL2, EL2 Read/Write Software Thread ID Register
1478 pub const tpidr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b010 };
1479 /// D19.2.150 TPIDR_EL3, EL3 Read/Write Software Thread ID Register
1480 pub const tpidr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b010 };
1481 /// D19.2.151 TPIDRRO_EL0, EL0 Read-Only Software Thread ID Register
1482 pub const tpidrro_el3: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b011 };
1483 /// D19.2.152 TTBR0_EL1, Translation Table Base Register 0 (EL1)
1484 pub const ttbr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b000 };
1485 /// D19.2.152 TTBR0_EL12, Translation Table Base Register 0 (EL12)
1486 pub const ttbr0_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b000 };
1487 /// D19.2.153 TTBR0_EL2, Translation Table Base Register 0 (EL2)
1488 pub const ttbr0_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b000 };
1489 /// D19.2.154 TTBR0_EL3, Translation Table Base Register 0 (EL3)
1490 pub const ttbr0_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b000 };
1491 /// D19.2.155 TTBR1_EL1, Translation Table Base Register 1 (EL1)
1492 pub const ttbr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b001 };
1493 /// D19.2.155 TTBR1_EL12, Translation Table Base Register 1 (EL12)
1494 pub const ttbr1_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b001 };
1495 /// D19.2.156 TTBR1_EL2, Translation Table Base Register 1 (EL2)
1496 pub const ttbr1_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b001 };
1497 /// D19.2.157 VBAR_EL1, Vector Base Address Register (EL1)
1498 pub const vbar_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b000 };
1499 /// D19.2.157 VBAR_EL12, Vector Base Address Register (EL12)
1500 pub const vbar_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b000 };
1501 /// D19.2.158 VBAR_EL2, Vector Base Address Register (EL2)
1502 pub const vbar_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b000 };
1503 /// D19.2.159 VBAR_EL3, Vector Base Address Register (EL3)
1504 pub const vbar_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b000 };
1505 /// D19.2.160 VMPIDR_EL2, Virtualization Multiprocessor ID Register
1506 pub const vmpidr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b101 };
1507 /// D19.2.161 VNCR_EL2, Virtual Nested Control Register
1508 pub const nvcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b000 };
1509 /// D19.2.162 VPIDR_EL2, Virtualization Processor ID Register
1510 pub const vpidr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b000 };
1511 /// D19.2.163 VSTCR_EL2, Virtualization Secure Translation Control Register
1512 pub const vstcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0110, .op2 = 0b010 };
1513 /// D19.2.164 VSTTBR_EL2, Virtualization Secure Translation Table Base Register
1514 pub const vsttbr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0110, .op2 = 0b000 };
1515 /// D19.2.165 VTCR_EL2, Virtualization Translation Control Register
1516 pub const vtcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b010 };
1517 /// D19.2.166 VTTBR_EL2, Virtualization Translation Table Base Register
1518 pub const vttbr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b000 };
1519 /// D19.2.167 ZCR_EL1, SVE Control Register (EL1)
1520 pub const zcr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b000 };
1521 /// D19.2.167 ZCR_EL12, SVE Control Register (EL12)
1522 pub const zcr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b000 };
1523 /// D19.2.168 ZCR_EL2, SVE Control Register (EL2)
1524 pub const zcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b000 };
1525 /// D19.2.169 ZCR_EL3, SVE Control Register (EL3)
1526 pub const zcr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b000 };
1527
1528 pub fn parse(reg: []const u8) ?System {
1529 if (reg.len >= 10 and std.ascii.toLower(reg[0]) == 's') encoded: {
1530 var symbol_it = std.mem.splitScalar(u8, reg[1..], '_');
1531 const op0 = std.fmt.parseInt(u2, symbol_it.next() orelse break :encoded, 10) catch break :encoded;
1532 if (op0 < 0b10) break :encoded;
1533 const op1 = std.fmt.parseInt(u3, symbol_it.next() orelse break :encoded, 10) catch break :encoded;
1534 const n = symbol_it.next() orelse break :encoded;
1535 if (n.len == 0 or std.ascii.toLower(n[0]) != 'c') break :encoded;
1536 const CRn = std.fmt.parseInt(u4, n[1..], 10) catch break :encoded;
1537 const m = symbol_it.next() orelse break :encoded;
1538 if (m.len == 0 or std.ascii.toLower(m[0]) != 'c') break :encoded;
1539 const CRm = std.fmt.parseInt(u4, m[1..], 10) catch break :encoded;
1540 const op2 = std.fmt.parseInt(u3, symbol_it.next() orelse break :encoded, 10) catch break :encoded;
1541 if (symbol_it.next() != null) break :encoded;
1542 return .{ .op0 = op0, .op1 = op1, .CRn = CRn, .CRm = CRm, .op2 = op2 };
1543 }
1544 inline for (@typeInfo(System).@"struct".decls) |decl| {
1545 if (@TypeOf(@field(System, decl.name)) != System) continue;
1546 if (toLowerEqlAssertLower(reg, decl.name)) return @field(System, decl.name);
1547 }
1548 return null;
1549 }
1550 };
1551
1552 fn toLowerEqlAssertLower(lhs: []const u8, rhs: []const u8) bool {
1553 if (lhs.len != rhs.len) return false;
1554 for (lhs, rhs) |l, r| {
1555 assert(!std.ascii.isUpper(r));
1556 if (std.ascii.toLower(l) != r) return false;
1557 }
1558 return true;
1559 }
1144};1560};
11451561
1146/// C1.2.4 Condition code1562/// C1.2.4 Condition code
...@@ -2385,12 +2801,7 @@ pub const Instruction = packed union {...@@ -2385,12 +2801,7 @@ pub const Instruction = packed union {
23852801
2386 pub const Group = packed struct {2802 pub const Group = packed struct {
2387 Rt: Register.Encoded,2803 Rt: Register.Encoded,
2388 op2: u3,2804 systemreg: Register.System,
2389 CRm: u4,
2390 CRn: u4,
2391 op1: u3,
2392 o0: u1,
2393 decoded20: u1 = 0b1,
2394 L: L,2805 L: L,
2395 decoded22: u10 = 0b1101010100,2806 decoded22: u10 = 0b1101010100,
2396 };2807 };
...@@ -2398,12 +2809,7 @@ pub const Instruction = packed union {...@@ -2398,12 +2809,7 @@ pub const Instruction = packed union {
2398 /// C6.2.230 MSR (register)2809 /// C6.2.230 MSR (register)
2399 pub const Msr = packed struct {2810 pub const Msr = packed struct {
2400 Rt: Register.Encoded,2811 Rt: Register.Encoded,
2401 op2: u3,2812 systemreg: Register.System,
2402 CRm: u4,
2403 CRn: u4,
2404 op1: u3,
2405 o0: u1,
2406 decoded20: u1 = 0b1,
2407 L: L = .msr,2813 L: L = .msr,
2408 decoded22: u10 = 0b1101010100,2814 decoded22: u10 = 0b1101010100,
2409 };2815 };
...@@ -2411,12 +2817,7 @@ pub const Instruction = packed union {...@@ -2411,12 +2817,7 @@ pub const Instruction = packed union {
2411 /// C6.2.228 MRS2817 /// C6.2.228 MRS
2412 pub const Mrs = packed struct {2818 pub const Mrs = packed struct {
2413 Rt: Register.Encoded,2819 Rt: Register.Encoded,
2414 op2: u3,2820 systemreg: Register.System,
2415 CRm: u4,
2416 CRn: u4,
2417 op1: u3,
2418 o0: u1,
2419 decoded20: u1 = 0b1,
2420 L: L = .mrs,2821 L: L = .mrs,
2421 decoded22: u10 = 0b1101010100,2822 decoded22: u10 = 0b1101010100,
2422 };2823 };
...@@ -10585,30 +10986,22 @@ pub const Instruction = packed union {...@@ -10585,30 +10986,22 @@ pub const Instruction = packed union {
10585 } } };10986 } } };
10586 }10987 }
10587 /// C6.2.228 MRS10988 /// C6.2.228 MRS
10588 pub fn mrs(t: Register, op0: u2, op1: u3, n: u4, m: u4, op2: u3) Instruction {10989 pub fn mrs(t: Register, systemreg: Register.System) Instruction {
10589 assert(t.format.integer == .doubleword);10990 assert(t.format.integer == .doubleword and systemreg.op0 >= 0b10);
10590 return .{ .branch_exception_generating_system = .{ .system_register_move = .{10991 return .{ .branch_exception_generating_system = .{ .system_register_move = .{
10591 .mrs = .{10992 .mrs = .{
10592 .Rt = t.alias.encode(.{}),10993 .Rt = t.alias.encode(.{}),
10593 .op2 = op2,10994 .systemreg = systemreg,
10594 .CRm = m,
10595 .CRn = n,
10596 .op1 = op1,
10597 .o0 = @intCast(op0 - 0b10),
10598 },10995 },
10599 } } };10996 } } };
10600 }10997 }
10601 /// C6.2.230 MSR (register)10998 /// C6.2.230 MSR (register)
10602 pub fn msr(op0: u2, op1: u3, n: u4, m: u4, op2: u3, t: Register) Instruction {10999 pub fn msr(systemreg: Register.System, t: Register) Instruction {
10603 assert(t.format.integer == .doubleword);11000 assert(systemreg.op0 >= 0b10 and t.format.integer == .doubleword);
10604 return .{ .branch_exception_generating_system = .{ .system_register_move = .{11001 return .{ .branch_exception_generating_system = .{ .system_register_move = .{
10605 .msr = .{11002 .msr = .{
10606 .Rt = t.alias.encode(.{}),11003 .Rt = t.alias.encode(.{}),
10607 .op2 = op2,11004 .systemreg = systemreg,
10608 .CRm = m,
10609 .CRn = n,
10610 .op1 = op1,
10611 .o0 = @intCast(op0 - 0b10),
10612 },11005 },
10613 } } };11006 } } };
10614 }11007 }
src/codegen/aarch64/instructions.zon+12-2
...@@ -851,11 +851,21 @@...@@ -851,11 +851,21 @@
851 },851 },
852 // C6.2.228 MRS852 // C6.2.228 MRS
853 .{853 .{
854 .pattern = "MRS <Xt>, CTR_EL0",854 .pattern = "MRS <Xt>, <systemreg>",
855 .symbols = .{855 .symbols = .{
856 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },856 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
857 .systemreg = .systemreg,
857 },858 },
858 .encode = .{ .mrs, .Xt, 0b11, 0b011, 0b0000, 0b0000, 0b001 },859 .encode = .{ .mrs, .Xt, .systemreg },
860 },
861 // C6.2.230 MSR (register)
862 .{
863 .pattern = "MSR <systemreg>, <Xt>",
864 .symbols = .{
865 .systemreg = .systemreg,
866 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
867 },
868 .encode = .{ .msr, .systemreg, .Xt },
859 },869 },
860 // C6.2.234 NEG870 // C6.2.234 NEG
861 .{871 .{
test/behavior/basic.zig-3
...@@ -471,7 +471,6 @@ fn testPointerToVoidReturnType2() *const void {...@@ -471,7 +471,6 @@ fn testPointerToVoidReturnType2() *const void {
471}471}
472472
473test "array 2D const double ptr" {473test "array 2D const double ptr" {
474 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
475 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO474 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
476 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;475 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
477 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;476 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -484,7 +483,6 @@ test "array 2D const double ptr" {...@@ -484,7 +483,6 @@ test "array 2D const double ptr" {
484}483}
485484
486test "array 2D const double ptr with offset" {485test "array 2D const double ptr with offset" {
487 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
488 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO486 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
489 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;487 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
490 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;488 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -497,7 +495,6 @@ test "array 2D const double ptr with offset" {...@@ -497,7 +495,6 @@ test "array 2D const double ptr with offset" {
497}495}
498496
499test "array 3D const double ptr with offset" {497test "array 3D const double ptr with offset" {
500 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
501 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO498 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
502 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;499 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
503 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;500 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/cast.zig-1
...@@ -1816,7 +1816,6 @@ test "peer type resolution: C pointer and @TypeOf(null)" {...@@ -1816,7 +1816,6 @@ test "peer type resolution: C pointer and @TypeOf(null)" {
1816}1816}
18171817
1818test "peer type resolution: three-way resolution combines error set and optional" {1818test "peer type resolution: three-way resolution combines error set and optional" {
1819 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1820 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1819 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1821 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1820 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1822 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1821 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/pointers.zig-1
...@@ -436,7 +436,6 @@ test "pointer sentinel with optional element" {...@@ -436,7 +436,6 @@ test "pointer sentinel with optional element" {
436}436}
437437
438test "pointer sentinel with +inf" {438test "pointer sentinel with +inf" {
439 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
440 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO439 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
441 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO440 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
442 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;441 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;