authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-15 10:44:00-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-08-15 10:44:00-07:00
log6d7c6a0f4e4f77e10462c3d8becf4e51fe172ccf
tree195f754a6aa24d8dbddbe91139edb59a971bd067
parentc1eff72c4a0a9d036299b322184f271f6a61ea28
parent56d62395d146a6622d8b751bfed353bdd86e1421
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #24856 from jacobly0/aarch64-oom

aarch64: more assembler instructions

4 files changed, 1463 insertions(+), 179 deletions(-)

src/codegen/aarch64/Assemble.zig+669-157
......@@ -6,11 +6,9 @@ pub const Operand = union(enum) {
66};
77
88pub fn nextInstruction(as: *Assemble) !?Instruction {
9 @setEvalBranchQuota(140_000);
10 comptime var ct_token_buf: [token_buf_len]u8 = undefined;
11 var token_buf: [token_buf_len]u8 = undefined;
129 const original_source = while (true) {
1310 const original_source = as.source;
11 var token_buf: [token_buf_len]u8 = undefined;
1412 const source_token = try as.nextToken(&token_buf, .{});
1513 switch (source_token.len) {
1614 0 => return null,
......@@ -27,73 +25,9 @@ pub fn nextInstruction(as: *Assemble) !?Instruction {
2725 \\=========================
2826 \\
2927 , .{std.zig.fmtString(std.mem.span(original_source))});
30 inline for (instructions) |instruction| {
31 next_pattern: {
32 as.source = original_source;
33 const Symbols = @TypeOf(instruction.symbols);
34 var symbols: Symbols: {
35 const symbols = @typeInfo(Symbols).@"struct".fields;
36 var symbol_fields: [symbols.len]std.builtin.Type.StructField = undefined;
37 for (&symbol_fields, symbols) |*symbol_field, symbol| {
38 const Storage = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage();
39 symbol_field.* = .{
40 .name = symbol.name,
41 .type = Storage,
42 .default_value_ptr = null,
43 .is_comptime = false,
44 .alignment = @alignOf(Storage),
45 };
46 }
47 break :Symbols @Type(.{ .@"struct" = .{
48 .layout = .auto,
49 .fields = &symbol_fields,
50 .decls = &.{},
51 .is_tuple = false,
52 } });
53 } = undefined;
54 const Symbol = std.meta.FieldEnum(Symbols);
55 comptime var unused_symbols: std.enums.EnumSet(Symbol) = .initFull();
56 comptime var pattern_as: Assemble = .{ .source = instruction.pattern, .operands = undefined };
57 inline while (true) {
58 const pattern_token = comptime pattern_as.nextToken(&ct_token_buf, .{ .placeholders = true }) catch |err|
59 @compileError(@errorName(err) ++ " while parsing '" ++ instruction.pattern ++ "'");
60 const source_token = try as.nextToken(&token_buf, .{ .operands = true });
61 log.debug("\"{f}\" -> \"{f}\"", .{
62 std.zig.fmtString(pattern_token),
63 std.zig.fmtString(source_token),
64 });
65 if (pattern_token.len == 0) {
66 comptime var unused_symbol_it = unused_symbols.iterator();
67 inline while (comptime unused_symbol_it.next()) |unused_symbol|
68 @compileError(@tagName(unused_symbol) ++ " unused while parsing '" ++ instruction.pattern ++ "'");
69 switch (source_token.len) {
70 0 => {},
71 else => switch (source_token[0]) {
72 else => break :next_pattern,
73 '\n', ';' => {},
74 },
75 }
76 const encode = @field(Instruction, @tagName(instruction.encode[0]));
77 const Encode = @TypeOf(encode);
78 var args: std.meta.ArgsTuple(Encode) = undefined;
79 inline for (&args, @typeInfo(Encode).@"fn".params, 1..instruction.encode.len) |*arg, param, encode_index|
80 arg.* = zonCast(param.type.?, instruction.encode[encode_index], symbols);
81 return @call(.auto, encode, args);
82 } else if (pattern_token[0] == '<') {
83 const symbol_name = comptime pattern_token[1 .. std.mem.indexOfScalarPos(u8, pattern_token, 1, '|') orelse
84 pattern_token.len - 1];
85 const symbol = @field(Symbol, symbol_name);
86 const symbol_ptr = &@field(symbols, symbol_name);
87 const symbol_value = zonCast(SymbolSpec, @field(instruction.symbols, symbol_name), .{}).parse(source_token) orelse break :next_pattern;
88 if (comptime unused_symbols.contains(symbol)) {
89 log.debug("{s} = {any}", .{ symbol_name, symbol_value });
90 symbol_ptr.* = symbol_value;
91 comptime unused_symbols.remove(symbol);
92 } else if (symbol_ptr.* != symbol_value) break :next_pattern;
93 } else if (!toUpperEqlAssertUpper(source_token, pattern_token)) break :next_pattern;
94 }
95 }
96 log.debug("'{s}' not matched...", .{instruction.pattern});
28 for (matchers) |matcher| {
29 as.source = original_source;
30 if (try matcher(as)) |result| return result;
9731 }
9832 as.source = original_source;
9933 log.debug("Nothing matched!\n", .{});
......@@ -106,6 +40,12 @@ fn zonCast(comptime Result: type, zon_value: anytype, symbols: anytype) Result {
10640 switch (@typeInfo(ZonValue)) {
10741 .void, .bool, .int, .float, .pointer, .comptime_float, .comptime_int, .@"enum" => return zon_value,
10842 .@"struct" => |zon_struct| switch (@typeInfo(Result)) {
43 .pointer => |result_pointer| {
44 comptime assert(result_pointer.size == .slice and result_pointer.is_const);
45 var elems: [zon_value.len]result_pointer.child = undefined;
46 inline for (&elems, zon_value) |*elem, zon_elem| elem.* = zonCast(result_pointer.child, zon_elem, symbols);
47 return &elems;
48 },
10949 .@"struct" => |result_struct| {
11050 comptime var used_zon_fields = 0;
11151 var result: Result = undefined;
......@@ -158,6 +98,103 @@ fn zonCast(comptime Result: type, zon_value: anytype, symbols: anytype) Result {
15898 }
15999}
160100
101const matchers = matchers: {
102 const instructions = @import("instructions.zon");
103 var mut_matchers: [instructions.len]*const fn (as: *Assemble) error{InvalidSyntax}!?Instruction = undefined;
104 for (instructions, &mut_matchers) |instruction, *matcher| matcher.* = struct {
105 fn match(as: *Assemble) !?Instruction {
106 comptime for (@typeInfo(@TypeOf(instruction)).@"struct".fields) |field| {
107 if (std.mem.eql(u8, field.name, "requires")) continue;
108 if (std.mem.eql(u8, field.name, "pattern")) continue;
109 if (std.mem.eql(u8, field.name, "symbols")) continue;
110 if (std.mem.eql(u8, field.name, "encode")) continue;
111 @compileError("unexpected field '" ++ field.name ++ "'");
112 };
113 if (@hasField(@TypeOf(instruction), "requires")) _ = zonCast(
114 []const std.Target.aarch64.Feature,
115 instruction.requires,
116 .{},
117 );
118 var symbols: Symbols: {
119 const symbols = @typeInfo(@TypeOf(instruction.symbols)).@"struct".fields;
120 var symbol_fields: [symbols.len]std.builtin.Type.StructField = undefined;
121 for (&symbol_fields, symbols) |*symbol_field, symbol| {
122 const Storage = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage();
123 symbol_field.* = .{
124 .name = symbol.name,
125 .type = Storage,
126 .default_value_ptr = null,
127 .is_comptime = false,
128 .alignment = @alignOf(Storage),
129 };
130 }
131 break :Symbols @Type(.{ .@"struct" = .{
132 .layout = .auto,
133 .fields = &symbol_fields,
134 .decls = &.{},
135 .is_tuple = false,
136 } });
137 } = undefined;
138 const Symbol = std.meta.FieldEnum(@TypeOf(instruction.symbols));
139 comptime var unused_symbols: std.enums.EnumSet(Symbol) = .initFull();
140 comptime var pattern_as: Assemble = .{ .source = instruction.pattern, .operands = undefined };
141 inline while (true) {
142 comptime var ct_token_buf: [token_buf_len]u8 = undefined;
143 var token_buf: [token_buf_len]u8 = undefined;
144 const pattern_token = comptime pattern_as.nextToken(&ct_token_buf, .{ .placeholders = true }) catch |err|
145 @compileError(@errorName(err) ++ " while parsing '" ++ instruction.pattern ++ "'");
146 const source_token = try as.nextToken(&token_buf, .{ .operands = true });
147 log.debug("\"{f}\" -> \"{f}\"", .{
148 std.zig.fmtString(pattern_token),
149 std.zig.fmtString(source_token),
150 });
151 if (pattern_token.len == 0) {
152 comptime var unused_symbol_it = unused_symbols.iterator();
153 inline while (comptime unused_symbol_it.next()) |unused_symbol|
154 @compileError(@tagName(unused_symbol) ++ " unused while parsing '" ++ instruction.pattern ++ "'");
155 switch (source_token.len) {
156 0 => {},
157 else => switch (source_token[0]) {
158 else => {
159 log.debug("'{s}' not matched...", .{instruction.pattern});
160 return null;
161 },
162 '\n', ';' => {},
163 },
164 }
165 const encode = @field(Instruction, @tagName(instruction.encode[0]));
166 const Encode = @TypeOf(encode);
167 var args: std.meta.ArgsTuple(Encode) = undefined;
168 inline for (&args, @typeInfo(Encode).@"fn".params, 1..instruction.encode.len) |*arg, param, encode_index|
169 arg.* = zonCast(param.type.?, instruction.encode[encode_index], symbols);
170 return @call(.auto, encode, args);
171 } else if (pattern_token[0] == '<') {
172 const symbol_name = comptime pattern_token[1 .. std.mem.indexOfScalarPos(u8, pattern_token, 1, '|') orelse
173 pattern_token.len - 1];
174 const symbol = @field(Symbol, symbol_name);
175 const symbol_ptr = &@field(symbols, symbol_name);
176 const symbol_value = zonCast(SymbolSpec, @field(instruction.symbols, symbol_name), .{}).parse(source_token) orelse {
177 log.debug("'{s}' not matched...", .{instruction.pattern});
178 return null;
179 };
180 if (comptime unused_symbols.contains(symbol)) {
181 log.debug("{s} = {any}", .{ symbol_name, symbol_value });
182 symbol_ptr.* = symbol_value;
183 comptime unused_symbols.remove(symbol);
184 } else if (symbol_ptr.* != symbol_value) {
185 log.debug("'{s}' not matched...", .{instruction.pattern});
186 return null;
187 }
188 } else if (!toUpperEqlAssertUpper(source_token, pattern_token)) {
189 log.debug("'{s}' not matched...", .{instruction.pattern});
190 return null;
191 }
192 }
193 }
194 }.match;
195 break :matchers mut_matchers;
196};
197
161198fn toUpperEqlAssertUpper(lhs: []const u8, rhs: []const u8) bool {
162199 if (lhs.len != rhs.len) return false;
163200 for (lhs, rhs) |l, r| {
......@@ -281,9 +318,10 @@ const SymbolSpec = union(enum) {
281318 multiple_of: ?comptime_int = null,
282319 min_valid: ?comptime_int = null,
283320 max_valid: ?comptime_int = null,
321 adjust: enum { none, neg_wrap, dec } = .none,
284322 },
285323 fimm: struct { only_valid: ?f16 = null },
286 extend: struct { size: aarch64.encoding.Register.GeneralSize },
324 extend: struct { size: ?aarch64.encoding.Register.GeneralSize = null },
287325 shift: struct { allow_ror: bool = true },
288326 barrier: struct { only_sy: bool = false },
289327
......@@ -293,7 +331,7 @@ const SymbolSpec = union(enum) {
293331 .reg => aarch64.encoding.Register,
294332 .arrangement => aarch64.encoding.Register.Arrangement,
295333 .systemreg => aarch64.encoding.Register.System,
296 .imm => |imm| @Type(.{ .int = imm.type }),
334 .imm => |imm_spec| @Type(.{ .int = imm_spec.type }),
297335 .fimm => f16,
298336 .extend => Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option,
299337 .shift => Instruction.DataProcessingRegister.Shift.Op,
......@@ -372,7 +410,13 @@ const SymbolSpec = union(enum) {
372410 return systemreg;
373411 },
374412 .imm => |imm_spec| {
375 const imm = std.fmt.parseInt(Result, token, 0) catch {
413 const imm = std.fmt.parseInt(@Type(.{ .int = .{
414 .signedness = imm_spec.type.signedness,
415 .bits = switch (imm_spec.adjust) {
416 .none, .neg_wrap => imm_spec.type.bits,
417 .dec => imm_spec.type.bits + 1,
418 },
419 } }), token, 0) catch {
376420 log.debug("invalid immediate: \"{f}\"", .{std.zig.fmtString(token)});
377421 return null;
378422 };
......@@ -388,7 +432,14 @@ const SymbolSpec = union(enum) {
388432 log.debug("out of range immediate: \"{f}\"", .{std.zig.fmtString(token)});
389433 return null;
390434 };
391 return imm;
435 return switch (imm_spec.adjust) {
436 .none => imm,
437 .neg_wrap => -%imm,
438 .dec => std.math.cast(Result, imm - 1) orelse {
439 log.debug("out of range immediate: \"{f}\"", .{std.zig.fmtString(token)});
440 return null;
441 },
442 };
392443 },
393444 .fimm => |fimm_spec| {
394445 const full_fimm = std.fmt.parseFloat(f128, token) catch {
......@@ -433,10 +484,10 @@ const SymbolSpec = union(enum) {
433484 log.debug("invalid extend: \"{f}\"", .{std.zig.fmtString(token)});
434485 return null;
435486 };
436 if (extend.sf() != extend_spec.size) {
487 if (extend_spec.size) |size| if (extend.sf() != size) {
437488 log.debug("invalid extend: \"{f}\"", .{std.zig.fmtString(token)});
438489 return null;
439 }
490 };
440491 return extend;
441492 },
442493 .shift => |shift_spec| {
......@@ -488,6 +539,16 @@ const SymbolSpec = union(enum) {
488539test "add sub" {
489540 var as: Assemble = .{
490541 .source =
542 \\ adc w0, w0, w1
543 \\ adc w2, w3, w4
544 \\ adc w5, w5, wzr
545 \\ adc w6, w7, wzr
546 \\
547 \\ adcs w0, w0, w1
548 \\ adcs w2, w3, w4
549 \\ adcs w5, w5, wzr
550 \\ adcs w6, w7, wzr
551 \\
491552 \\ add w0, w0, w1
492553 \\ add w2, w3, w4
493554 \\ add wsp, w5, w6
......@@ -513,13 +574,13 @@ test "add sub" {
513574 \\ add w0, w0, w1
514575 \\ add w2, w3, w4, uxtb #0
515576 \\ add wsp, w5, w6, uxth #1
516 \\ add w7, wsp, w8, uxtw #0
517 \\ add wsp, wsp, w9, uxtw #2
518 \\ add w10, w10, wzr, uxtw #3
577 \\ add w7, wsp, w8, uxtw #2
578 \\ add wsp, wsp, w9, uxtx #0
579 \\ add w10, w10, wzr, uxtx #3
519580 \\ add w11, w12, wzr, sxtb #4
520581 \\ add wsp, w13, wzr, sxth #0
521582 \\ add w14, wsp, wzr, sxtw #1
522 \\ add wsp, wsp, wzr, sxtw #2
583 \\ add wsp, wsp, wzr, sxtx #2
523584 \\
524585 \\ add x0, x0, x1
525586 \\ add x2, x3, w4, uxtb #0
......@@ -582,6 +643,125 @@ test "add sub" {
582643 \\ add xzr, xzr, x13, asr #0x1F
583644 \\ add xzr, xzr, xzr, asr #0x3f
584645 \\
646 \\ addg x0, sp, #0, #0xf
647 \\ addg sp, x1, #0x3f0, #0
648 \\
649 \\ adds w0, w0, w1
650 \\ adds w2, w3, w4
651 \\ adds w5, w5, w6
652 \\ adds w7, wsp, w8
653 \\ adds w9, wsp, w9
654 \\ adds w10, w10, wzr
655 \\ adds w11, w12, wzr
656 \\ adds wzr, w13, wzr
657 \\ adds w14, wsp, wzr
658 \\ adds wzr, wsp, wzr
659 \\
660 \\ adds x0, x0, x1
661 \\ adds x2, x3, x4
662 \\ adds x5, x5, x6
663 \\ adds x7, sp, x8
664 \\ adds x9, sp, x9
665 \\ adds x10, x10, xzr
666 \\ adds x11, x12, xzr
667 \\ adds xzr, x13, xzr
668 \\ adds x14, sp, xzr
669 \\ adds xzr, sp, xzr
670 \\
671 \\ adds w0, w0, w1
672 \\ adds w2, w3, w4, uxtb #0
673 \\ adds wzr, w5, w6, uxth #1
674 \\ adds w7, wsp, w8, uxtw #2
675 \\ adds w9, wsp, w9, uxtx #0
676 \\ adds w10, w10, wzr, uxtx #3
677 \\ adds w11, w12, wzr, sxtb #4
678 \\ adds wzr, w13, wzr, sxth #0
679 \\ adds w14, wsp, wzr, sxtw #1
680 \\ adds wzr, wsp, wzr, sxtx #2
681 \\
682 \\ adds x0, x0, x1
683 \\ adds x2, x3, w4, uxtb #0
684 \\ adds xzr, x5, w6, uxth #1
685 \\ adds x7, sp, w8, uxtw #2
686 \\ adds xzr, sp, x9, uxtx #0
687 \\ adds x10, x10, xzr, uxtx #3
688 \\ adds x11, x12, wzr, sxtb #4
689 \\ adds xzr, x13, wzr, sxth #0
690 \\ adds x14, sp, wzr, sxtw #1
691 \\ adds xzr, sp, xzr, sxtx #2
692 \\
693 \\ adds w0, w0, #0
694 \\ adds w0, w1, #1, lsl #0
695 \\ adds wzr, w2, #2, lsl #12
696 \\ adds w3, wsp, #3, lsl #0
697 \\ adds wzr, wsp, #4095, lsl #12
698 \\ adds w0, w1, #0
699 \\ adds w2, w3, #0, lsl #0
700 \\ adds w4, wsp, #0
701 \\ adds w5, wsp, #0, lsl #0
702 \\ adds wzr, w6, #0
703 \\ adds wzr, w7, #0, lsl #0
704 \\ adds wzr, wsp, #0
705 \\ adds wzr, wsp, #0, lsl #0
706 \\
707 \\ adds x0, x0, #0
708 \\ adds x0, x1, #1, lsl #0
709 \\ adds xzr, x2, #2, lsl #12
710 \\ adds x3, sp, #3, lsl #0
711 \\ adds xzr, sp, #4095, lsl #12
712 \\ adds x0, x1, #0
713 \\ adds x2, x3, #0, lsl #0
714 \\ adds x4, sp, #0
715 \\ adds x5, sp, #0, lsl #0
716 \\ adds xzr, x6, #0
717 \\ adds xzr, x7, #0, lsl #0
718 \\ adds xzr, sp, #0
719 \\ adds xzr, sp, #0, lsl #0
720 \\
721 \\ adds w0, w0, w0
722 \\ adds w1, w1, w2, lsl #0
723 \\ adds w3, w4, w5, lsl #1
724 \\ adds w6, w6, wzr, lsl #31
725 \\ adds w7, wzr, w8, lsr #0
726 \\ adds w9, wzr, wzr, lsr #30
727 \\ adds wzr, w10, w11, lsr #31
728 \\ adds wzr, w12, wzr, asr #0x0
729 \\ adds wzr, wzr, w13, asr #0x10
730 \\ adds wzr, wzr, wzr, asr #0x1f
731 \\
732 \\ adds x0, x0, x0
733 \\ adds x1, x1, x2, lsl #0
734 \\ adds x3, x4, x5, lsl #1
735 \\ adds x6, x6, xzr, lsl #63
736 \\ adds x7, xzr, x8, lsr #0
737 \\ adds x9, xzr, xzr, lsr #62
738 \\ adds xzr, x10, x11, lsr #63
739 \\ adds xzr, x12, xzr, asr #0x0
740 \\ adds xzr, xzr, x13, asr #0x1F
741 \\ adds xzr, xzr, xzr, asr #0x3f
742 \\
743 \\ neg w0, w0
744 \\ neg w1, w2, lsl #0
745 \\ neg w3, wzr, lsl #7
746 \\ neg wzr, w4, lsr #14
747 \\ neg wzr, wzr, asr #21
748 \\
749 \\ neg x0, x0
750 \\ neg x1, x2, lsl #0
751 \\ neg x3, xzr, lsl #11
752 \\ neg xzr, x4, lsr #22
753 \\ neg xzr, xzr, asr #33
754 \\
755 \\ sbc w0, w0, w1
756 \\ sbc w2, w3, w4
757 \\ sbc w5, w5, wzr
758 \\ sbc w6, w7, wzr
759 \\
760 \\ sbcs w0, w0, w1
761 \\ sbcs w2, w3, w4
762 \\ sbcs w5, w5, wzr
763 \\ sbcs w6, w7, wzr
764 \\
585765 \\ sub w0, w0, w1
586766 \\ sub w2, w3, w4
587767 \\ sub wsp, w5, w6
......@@ -607,13 +787,13 @@ test "add sub" {
607787 \\ sub w0, w0, w1
608788 \\ sub w2, w3, w4, uxtb #0
609789 \\ sub wsp, w5, w6, uxth #1
610 \\ sub w7, wsp, w8, uxtw #0
611 \\ sub wsp, wsp, w9, uxtw #2
612 \\ sub w10, w10, wzr, uxtw #3
790 \\ sub w7, wsp, w8, uxtw #2
791 \\ sub wsp, wsp, w9, uxtx #0
792 \\ sub w10, w10, wzr, uxtx #3
613793 \\ sub w11, w12, wzr, sxtb #4
614794 \\ sub wsp, w13, wzr, sxth #0
615795 \\ sub w14, wsp, wzr, sxtw #1
616 \\ sub wsp, wsp, wzr, sxtw #2
796 \\ sub wsp, wsp, wzr, sxtx #2
617797 \\
618798 \\ sub x0, x0, x1
619799 \\ sub x2, x3, w4, uxtb #0
......@@ -676,21 +856,116 @@ test "add sub" {
676856 \\ sub xzr, xzr, x13, asr #0x1F
677857 \\ sub xzr, xzr, xzr, asr #0x3f
678858 \\
679 \\ neg w0, w0
680 \\ neg w1, w2, lsl #0
681 \\ neg w3, wzr, lsl #7
682 \\ neg wzr, w4, lsr #14
683 \\ neg wzr, wzr, asr #21
684 \\
685 \\ neg x0, x0
686 \\ neg x1, x2, lsl #0
687 \\ neg x3, xzr, lsl #11
688 \\ neg xzr, x4, lsr #22
689 \\ neg xzr, xzr, asr #33
859 \\ subg x0, sp, #0, #0xf
860 \\ subg sp, x1, #0x3f0, #0
861 \\
862 \\ subs w0, w0, w1
863 \\ subs w2, w3, w4
864 \\ subs w5, w5, w6
865 \\ subs w7, wsp, w8
866 \\ subs w9, wsp, w9
867 \\ subs w10, w10, wzr
868 \\ subs w11, w12, wzr
869 \\ subs wzr, w13, wzr
870 \\ subs w14, wsp, wzr
871 \\ subs wzr, wsp, wzr
872 \\
873 \\ subs x0, x0, x1
874 \\ subs x2, x3, x4
875 \\ subs x5, x5, x6
876 \\ subs x7, sp, x8
877 \\ subs x9, sp, x9
878 \\ subs x10, x10, xzr
879 \\ subs x11, x12, xzr
880 \\ subs xzr, x13, xzr
881 \\ subs x14, sp, xzr
882 \\ subs xzr, sp, xzr
883 \\
884 \\ subs w0, w0, w1
885 \\ subs w2, w3, w4, uxtb #0
886 \\ subs wzr, w5, w6, uxth #1
887 \\ subs w7, wsp, w8, uxtw #2
888 \\ subs w9, wsp, w9, uxtx #0
889 \\ subs w10, w10, wzr, uxtx #3
890 \\ subs w11, w12, wzr, sxtb #4
891 \\ subs wzr, w13, wzr, sxth #0
892 \\ subs w14, wsp, wzr, sxtw #1
893 \\ subs wzr, wsp, wzr, sxtx #2
894 \\
895 \\ subs x0, x0, x1
896 \\ subs x2, x3, w4, uxtb #0
897 \\ subs xzr, x5, w6, uxth #1
898 \\ subs x7, sp, w8, uxtw #2
899 \\ subs xzr, sp, x9, uxtx #0
900 \\ subs x10, x10, xzr, uxtx #3
901 \\ subs x11, x12, wzr, sxtb #4
902 \\ subs xzr, x13, wzr, sxth #0
903 \\ subs x14, sp, wzr, sxtw #1
904 \\ subs xzr, sp, xzr, sxtx #2
905 \\
906 \\ subs w0, w0, #0
907 \\ subs w0, w1, #1, lsl #0
908 \\ subs wzr, w2, #2, lsl #12
909 \\ subs w3, wsp, #3, lsl #0
910 \\ subs wzr, wsp, #4095, lsl #12
911 \\ subs w0, w1, #0
912 \\ subs w2, w3, #0, lsl #0
913 \\ subs w4, wsp, #0
914 \\ subs w5, wsp, #0, lsl #0
915 \\ subs wzr, w6, #0
916 \\ subs wzr, w7, #0, lsl #0
917 \\ subs wzr, wsp, #0
918 \\ subs wzr, wsp, #0, lsl #0
919 \\
920 \\ subs x0, x0, #0
921 \\ subs x0, x1, #1, lsl #0
922 \\ subs xzr, x2, #2, lsl #12
923 \\ subs x3, sp, #3, lsl #0
924 \\ subs xzr, sp, #4095, lsl #12
925 \\ subs x0, x1, #0
926 \\ subs x2, x3, #0, lsl #0
927 \\ subs x4, sp, #0
928 \\ subs x5, sp, #0, lsl #0
929 \\ subs xzr, x6, #0
930 \\ subs xzr, x7, #0, lsl #0
931 \\ subs xzr, sp, #0
932 \\ subs xzr, sp, #0, lsl #0
933 \\
934 \\ subs w0, w0, w0
935 \\ subs w1, w1, w2, lsl #0
936 \\ subs w3, w4, w5, lsl #1
937 \\ subs w6, w6, wzr, lsl #31
938 \\ subs w7, wzr, w8, lsr #0
939 \\ subs w9, wzr, wzr, lsr #30
940 \\ subs wzr, w10, w11, lsr #31
941 \\ subs wzr, w12, wzr, asr #0x0
942 \\ subs wzr, wzr, w13, asr #0x10
943 \\ subs wzr, wzr, wzr, asr #0x1f
944 \\
945 \\ subs x0, x0, x0
946 \\ subs x1, x1, x2, lsl #0
947 \\ subs x3, x4, x5, lsl #1
948 \\ subs x6, x6, xzr, lsl #63
949 \\ subs x7, xzr, x8, lsr #0
950 \\ subs x9, xzr, xzr, lsr #62
951 \\ subs xzr, x10, x11, lsr #63
952 \\ subs xzr, x12, xzr, asr #0x0
953 \\ subs xzr, xzr, x13, asr #0x1F
954 \\ subs xzr, xzr, xzr, asr #0x3f
690955 ,
691956 .operands = .empty,
692957 };
693958
959 try std.testing.expectFmt("adc w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
960 try std.testing.expectFmt("adc w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
961 try std.testing.expectFmt("adc w5, w5, wzr", "{f}", .{(try as.nextInstruction()).?});
962 try std.testing.expectFmt("adc w6, w7, wzr", "{f}", .{(try as.nextInstruction()).?});
963
964 try std.testing.expectFmt("adcs w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
965 try std.testing.expectFmt("adcs w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
966 try std.testing.expectFmt("adcs w5, w5, wzr", "{f}", .{(try as.nextInstruction()).?});
967 try std.testing.expectFmt("adcs w6, w7, wzr", "{f}", .{(try as.nextInstruction()).?});
968
694969 try std.testing.expectFmt("add w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
695970 try std.testing.expectFmt("add w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
696971 try std.testing.expectFmt("add wsp, w5, w6", "{f}", .{(try as.nextInstruction()).?});
......@@ -714,24 +989,24 @@ test "add sub" {
714989 try std.testing.expectFmt("add sp, sp, xzr", "{f}", .{(try as.nextInstruction()).?});
715990
716991 try std.testing.expectFmt("add w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
717 try std.testing.expectFmt("add w2, w3, w4, uxtb #0", "{f}", .{(try as.nextInstruction()).?});
992 try std.testing.expectFmt("add w2, w3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
718993 try std.testing.expectFmt("add wsp, w5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
719 try std.testing.expectFmt("add w7, wsp, w8", "{f}", .{(try as.nextInstruction()).?});
720 try std.testing.expectFmt("add wsp, wsp, w9, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
721 try std.testing.expectFmt("add w10, w10, wzr, uxtw #3", "{f}", .{(try as.nextInstruction()).?});
994 try std.testing.expectFmt("add w7, wsp, w8, lsl #2", "{f}", .{(try as.nextInstruction()).?});
995 try std.testing.expectFmt("add wsp, wsp, w9, uxtx", "{f}", .{(try as.nextInstruction()).?});
996 try std.testing.expectFmt("add w10, w10, wzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
722997 try std.testing.expectFmt("add w11, w12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
723 try std.testing.expectFmt("add wsp, w13, wzr, sxth #0", "{f}", .{(try as.nextInstruction()).?});
998 try std.testing.expectFmt("add wsp, w13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
724999 try std.testing.expectFmt("add w14, wsp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
725 try std.testing.expectFmt("add wsp, wsp, wzr, sxtw #2", "{f}", .{(try as.nextInstruction()).?});
1000 try std.testing.expectFmt("add wsp, wsp, wzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
7261001
7271002 try std.testing.expectFmt("add x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
728 try std.testing.expectFmt("add x2, x3, w4, uxtb #0", "{f}", .{(try as.nextInstruction()).?});
1003 try std.testing.expectFmt("add x2, x3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
7291004 try std.testing.expectFmt("add sp, x5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
7301005 try std.testing.expectFmt("add x7, sp, w8, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
7311006 try std.testing.expectFmt("add sp, sp, x9", "{f}", .{(try as.nextInstruction()).?});
7321007 try std.testing.expectFmt("add x10, x10, xzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
7331008 try std.testing.expectFmt("add x11, x12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
734 try std.testing.expectFmt("add sp, x13, wzr, sxth #0", "{f}", .{(try as.nextInstruction()).?});
1009 try std.testing.expectFmt("add sp, x13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
7351010 try std.testing.expectFmt("add x14, sp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
7361011 try std.testing.expectFmt("add sp, sp, xzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
7371012
......@@ -785,6 +1060,125 @@ test "add sub" {
7851060 try std.testing.expectFmt("add xzr, xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
7861061 try std.testing.expectFmt("add xzr, xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
7871062
1063 try std.testing.expectFmt("addg x0, sp, #0x0, #0xf", "{f}", .{(try as.nextInstruction()).?});
1064 try std.testing.expectFmt("addg sp, x1, #0x3f0, #0x0", "{f}", .{(try as.nextInstruction()).?});
1065
1066 try std.testing.expectFmt("adds w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
1067 try std.testing.expectFmt("adds w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
1068 try std.testing.expectFmt("adds w5, w5, w6", "{f}", .{(try as.nextInstruction()).?});
1069 try std.testing.expectFmt("adds w7, wsp, w8", "{f}", .{(try as.nextInstruction()).?});
1070 try std.testing.expectFmt("adds w9, wsp, w9", "{f}", .{(try as.nextInstruction()).?});
1071 try std.testing.expectFmt("adds w10, w10, wzr", "{f}", .{(try as.nextInstruction()).?});
1072 try std.testing.expectFmt("adds w11, w12, wzr", "{f}", .{(try as.nextInstruction()).?});
1073 try std.testing.expectFmt("cmn w13, wzr", "{f}", .{(try as.nextInstruction()).?});
1074 try std.testing.expectFmt("adds w14, wsp, wzr", "{f}", .{(try as.nextInstruction()).?});
1075 try std.testing.expectFmt("cmn wsp, wzr", "{f}", .{(try as.nextInstruction()).?});
1076
1077 try std.testing.expectFmt("adds x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
1078 try std.testing.expectFmt("adds x2, x3, x4", "{f}", .{(try as.nextInstruction()).?});
1079 try std.testing.expectFmt("adds x5, x5, x6", "{f}", .{(try as.nextInstruction()).?});
1080 try std.testing.expectFmt("adds x7, sp, x8", "{f}", .{(try as.nextInstruction()).?});
1081 try std.testing.expectFmt("adds x9, sp, x9", "{f}", .{(try as.nextInstruction()).?});
1082 try std.testing.expectFmt("adds x10, x10, xzr", "{f}", .{(try as.nextInstruction()).?});
1083 try std.testing.expectFmt("adds x11, x12, xzr", "{f}", .{(try as.nextInstruction()).?});
1084 try std.testing.expectFmt("cmn x13, xzr", "{f}", .{(try as.nextInstruction()).?});
1085 try std.testing.expectFmt("adds x14, sp, xzr", "{f}", .{(try as.nextInstruction()).?});
1086 try std.testing.expectFmt("cmn sp, xzr", "{f}", .{(try as.nextInstruction()).?});
1087
1088 try std.testing.expectFmt("adds w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
1089 try std.testing.expectFmt("adds w2, w3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
1090 try std.testing.expectFmt("cmn w5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
1091 try std.testing.expectFmt("adds w7, wsp, w8, lsl #2", "{f}", .{(try as.nextInstruction()).?});
1092 try std.testing.expectFmt("adds w9, wsp, w9, uxtx", "{f}", .{(try as.nextInstruction()).?});
1093 try std.testing.expectFmt("adds w10, w10, wzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
1094 try std.testing.expectFmt("adds w11, w12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
1095 try std.testing.expectFmt("cmn w13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
1096 try std.testing.expectFmt("adds w14, wsp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
1097 try std.testing.expectFmt("cmn wsp, wzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
1098
1099 try std.testing.expectFmt("adds x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
1100 try std.testing.expectFmt("adds x2, x3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
1101 try std.testing.expectFmt("cmn x5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
1102 try std.testing.expectFmt("adds x7, sp, w8, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
1103 try std.testing.expectFmt("cmn sp, x9", "{f}", .{(try as.nextInstruction()).?});
1104 try std.testing.expectFmt("adds x10, x10, xzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
1105 try std.testing.expectFmt("adds x11, x12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
1106 try std.testing.expectFmt("cmn x13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
1107 try std.testing.expectFmt("adds x14, sp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
1108 try std.testing.expectFmt("cmn sp, xzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
1109
1110 try std.testing.expectFmt("adds w0, w0, #0x0", "{f}", .{(try as.nextInstruction()).?});
1111 try std.testing.expectFmt("adds w0, w1, #0x1", "{f}", .{(try as.nextInstruction()).?});
1112 try std.testing.expectFmt("adds wzr, w2, #0x2, lsl #12", "{f}", .{(try as.nextInstruction()).?});
1113 try std.testing.expectFmt("adds w3, wsp, #0x3", "{f}", .{(try as.nextInstruction()).?});
1114 try std.testing.expectFmt("adds wzr, wsp, #0xfff, lsl #12", "{f}", .{(try as.nextInstruction()).?});
1115 try std.testing.expectFmt("adds w0, w1, #0x0", "{f}", .{(try as.nextInstruction()).?});
1116 try std.testing.expectFmt("adds w2, w3, #0x0", "{f}", .{(try as.nextInstruction()).?});
1117 try std.testing.expectFmt("adds w4, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1118 try std.testing.expectFmt("adds w5, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1119 try std.testing.expectFmt("adds wzr, w6, #0x0", "{f}", .{(try as.nextInstruction()).?});
1120 try std.testing.expectFmt("adds wzr, w7, #0x0", "{f}", .{(try as.nextInstruction()).?});
1121 try std.testing.expectFmt("adds wzr, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1122 try std.testing.expectFmt("adds wzr, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1123
1124 try std.testing.expectFmt("adds x0, x0, #0x0", "{f}", .{(try as.nextInstruction()).?});
1125 try std.testing.expectFmt("adds x0, x1, #0x1", "{f}", .{(try as.nextInstruction()).?});
1126 try std.testing.expectFmt("adds xzr, x2, #0x2, lsl #12", "{f}", .{(try as.nextInstruction()).?});
1127 try std.testing.expectFmt("adds x3, sp, #0x3", "{f}", .{(try as.nextInstruction()).?});
1128 try std.testing.expectFmt("adds xzr, sp, #0xfff, lsl #12", "{f}", .{(try as.nextInstruction()).?});
1129 try std.testing.expectFmt("adds x0, x1, #0x0", "{f}", .{(try as.nextInstruction()).?});
1130 try std.testing.expectFmt("adds x2, x3, #0x0", "{f}", .{(try as.nextInstruction()).?});
1131 try std.testing.expectFmt("adds x4, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1132 try std.testing.expectFmt("adds x5, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1133 try std.testing.expectFmt("adds xzr, x6, #0x0", "{f}", .{(try as.nextInstruction()).?});
1134 try std.testing.expectFmt("adds xzr, x7, #0x0", "{f}", .{(try as.nextInstruction()).?});
1135 try std.testing.expectFmt("adds xzr, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1136 try std.testing.expectFmt("adds xzr, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1137
1138 try std.testing.expectFmt("adds w0, w0, w0", "{f}", .{(try as.nextInstruction()).?});
1139 try std.testing.expectFmt("adds w1, w1, w2", "{f}", .{(try as.nextInstruction()).?});
1140 try std.testing.expectFmt("adds w3, w4, w5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
1141 try std.testing.expectFmt("adds w6, w6, wzr, lsl #31", "{f}", .{(try as.nextInstruction()).?});
1142 try std.testing.expectFmt("adds w7, wzr, w8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
1143 try std.testing.expectFmt("adds w9, wzr, wzr, lsr #30", "{f}", .{(try as.nextInstruction()).?});
1144 try std.testing.expectFmt("cmn w10, w11, lsr #31", "{f}", .{(try as.nextInstruction()).?});
1145 try std.testing.expectFmt("cmn w12, wzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
1146 try std.testing.expectFmt("cmn wzr, w13, asr #16", "{f}", .{(try as.nextInstruction()).?});
1147 try std.testing.expectFmt("cmn wzr, wzr, asr #31", "{f}", .{(try as.nextInstruction()).?});
1148
1149 try std.testing.expectFmt("adds x0, x0, x0", "{f}", .{(try as.nextInstruction()).?});
1150 try std.testing.expectFmt("adds x1, x1, x2", "{f}", .{(try as.nextInstruction()).?});
1151 try std.testing.expectFmt("adds x3, x4, x5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
1152 try std.testing.expectFmt("adds x6, x6, xzr, lsl #63", "{f}", .{(try as.nextInstruction()).?});
1153 try std.testing.expectFmt("adds x7, xzr, x8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
1154 try std.testing.expectFmt("adds x9, xzr, xzr, lsr #62", "{f}", .{(try as.nextInstruction()).?});
1155 try std.testing.expectFmt("cmn x10, x11, lsr #63", "{f}", .{(try as.nextInstruction()).?});
1156 try std.testing.expectFmt("cmn x12, xzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
1157 try std.testing.expectFmt("cmn xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
1158 try std.testing.expectFmt("cmn xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
1159
1160 try std.testing.expectFmt("neg w0, w0", "{f}", .{(try as.nextInstruction()).?});
1161 try std.testing.expectFmt("neg w1, w2", "{f}", .{(try as.nextInstruction()).?});
1162 try std.testing.expectFmt("neg w3, wzr, lsl #7", "{f}", .{(try as.nextInstruction()).?});
1163 try std.testing.expectFmt("neg wzr, w4, lsr #14", "{f}", .{(try as.nextInstruction()).?});
1164 try std.testing.expectFmt("neg wzr, wzr, asr #21", "{f}", .{(try as.nextInstruction()).?});
1165
1166 try std.testing.expectFmt("neg x0, x0", "{f}", .{(try as.nextInstruction()).?});
1167 try std.testing.expectFmt("neg x1, x2", "{f}", .{(try as.nextInstruction()).?});
1168 try std.testing.expectFmt("neg x3, xzr, lsl #11", "{f}", .{(try as.nextInstruction()).?});
1169 try std.testing.expectFmt("neg xzr, x4, lsr #22", "{f}", .{(try as.nextInstruction()).?});
1170 try std.testing.expectFmt("neg xzr, xzr, asr #33", "{f}", .{(try as.nextInstruction()).?});
1171
1172 try std.testing.expectFmt("sbc w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
1173 try std.testing.expectFmt("sbc w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
1174 try std.testing.expectFmt("sbc w5, w5, wzr", "{f}", .{(try as.nextInstruction()).?});
1175 try std.testing.expectFmt("sbc w6, w7, wzr", "{f}", .{(try as.nextInstruction()).?});
1176
1177 try std.testing.expectFmt("sbcs w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
1178 try std.testing.expectFmt("sbcs w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
1179 try std.testing.expectFmt("sbcs w5, w5, wzr", "{f}", .{(try as.nextInstruction()).?});
1180 try std.testing.expectFmt("sbcs w6, w7, wzr", "{f}", .{(try as.nextInstruction()).?});
1181
7881182 try std.testing.expectFmt("sub w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
7891183 try std.testing.expectFmt("sub w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
7901184 try std.testing.expectFmt("sub wsp, w5, w6", "{f}", .{(try as.nextInstruction()).?});
......@@ -808,24 +1202,24 @@ test "add sub" {
8081202 try std.testing.expectFmt("sub sp, sp, xzr", "{f}", .{(try as.nextInstruction()).?});
8091203
8101204 try std.testing.expectFmt("sub w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
811 try std.testing.expectFmt("sub w2, w3, w4, uxtb #0", "{f}", .{(try as.nextInstruction()).?});
1205 try std.testing.expectFmt("sub w2, w3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
8121206 try std.testing.expectFmt("sub wsp, w5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
813 try std.testing.expectFmt("sub w7, wsp, w8", "{f}", .{(try as.nextInstruction()).?});
814 try std.testing.expectFmt("sub wsp, wsp, w9, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
815 try std.testing.expectFmt("sub w10, w10, wzr, uxtw #3", "{f}", .{(try as.nextInstruction()).?});
1207 try std.testing.expectFmt("sub w7, wsp, w8, lsl #2", "{f}", .{(try as.nextInstruction()).?});
1208 try std.testing.expectFmt("sub wsp, wsp, w9, uxtx", "{f}", .{(try as.nextInstruction()).?});
1209 try std.testing.expectFmt("sub w10, w10, wzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
8161210 try std.testing.expectFmt("sub w11, w12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
817 try std.testing.expectFmt("sub wsp, w13, wzr, sxth #0", "{f}", .{(try as.nextInstruction()).?});
1211 try std.testing.expectFmt("sub wsp, w13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
8181212 try std.testing.expectFmt("sub w14, wsp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
819 try std.testing.expectFmt("sub wsp, wsp, wzr, sxtw #2", "{f}", .{(try as.nextInstruction()).?});
1213 try std.testing.expectFmt("sub wsp, wsp, wzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
8201214
8211215 try std.testing.expectFmt("sub x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
822 try std.testing.expectFmt("sub x2, x3, w4, uxtb #0", "{f}", .{(try as.nextInstruction()).?});
1216 try std.testing.expectFmt("sub x2, x3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
8231217 try std.testing.expectFmt("sub sp, x5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
8241218 try std.testing.expectFmt("sub x7, sp, w8, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
8251219 try std.testing.expectFmt("sub sp, sp, x9", "{f}", .{(try as.nextInstruction()).?});
8261220 try std.testing.expectFmt("sub x10, x10, xzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
8271221 try std.testing.expectFmt("sub x11, x12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
828 try std.testing.expectFmt("sub sp, x13, wzr, sxth #0", "{f}", .{(try as.nextInstruction()).?});
1222 try std.testing.expectFmt("sub sp, x13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
8291223 try std.testing.expectFmt("sub x14, sp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
8301224 try std.testing.expectFmt("sub sp, sp, xzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
8311225
......@@ -879,17 +1273,102 @@ test "add sub" {
8791273 try std.testing.expectFmt("neg xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
8801274 try std.testing.expectFmt("neg xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
8811275
882 try std.testing.expectFmt("neg w0, w0", "{f}", .{(try as.nextInstruction()).?});
883 try std.testing.expectFmt("neg w1, w2", "{f}", .{(try as.nextInstruction()).?});
884 try std.testing.expectFmt("neg w3, wzr, lsl #7", "{f}", .{(try as.nextInstruction()).?});
885 try std.testing.expectFmt("neg wzr, w4, lsr #14", "{f}", .{(try as.nextInstruction()).?});
886 try std.testing.expectFmt("neg wzr, wzr, asr #21", "{f}", .{(try as.nextInstruction()).?});
887
888 try std.testing.expectFmt("neg x0, x0", "{f}", .{(try as.nextInstruction()).?});
889 try std.testing.expectFmt("neg x1, x2", "{f}", .{(try as.nextInstruction()).?});
890 try std.testing.expectFmt("neg x3, xzr, lsl #11", "{f}", .{(try as.nextInstruction()).?});
891 try std.testing.expectFmt("neg xzr, x4, lsr #22", "{f}", .{(try as.nextInstruction()).?});
892 try std.testing.expectFmt("neg xzr, xzr, asr #33", "{f}", .{(try as.nextInstruction()).?});
1276 try std.testing.expectFmt("subg x0, sp, #0x0, #0xf", "{f}", .{(try as.nextInstruction()).?});
1277 try std.testing.expectFmt("subg sp, x1, #0x3f0, #0x0", "{f}", .{(try as.nextInstruction()).?});
1278
1279 try std.testing.expectFmt("subs w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
1280 try std.testing.expectFmt("subs w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
1281 try std.testing.expectFmt("subs w5, w5, w6", "{f}", .{(try as.nextInstruction()).?});
1282 try std.testing.expectFmt("subs w7, wsp, w8", "{f}", .{(try as.nextInstruction()).?});
1283 try std.testing.expectFmt("subs w9, wsp, w9", "{f}", .{(try as.nextInstruction()).?});
1284 try std.testing.expectFmt("subs w10, w10, wzr", "{f}", .{(try as.nextInstruction()).?});
1285 try std.testing.expectFmt("subs w11, w12, wzr", "{f}", .{(try as.nextInstruction()).?});
1286 try std.testing.expectFmt("cmp w13, wzr", "{f}", .{(try as.nextInstruction()).?});
1287 try std.testing.expectFmt("subs w14, wsp, wzr", "{f}", .{(try as.nextInstruction()).?});
1288 try std.testing.expectFmt("cmp wsp, wzr", "{f}", .{(try as.nextInstruction()).?});
1289
1290 try std.testing.expectFmt("subs x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
1291 try std.testing.expectFmt("subs x2, x3, x4", "{f}", .{(try as.nextInstruction()).?});
1292 try std.testing.expectFmt("subs x5, x5, x6", "{f}", .{(try as.nextInstruction()).?});
1293 try std.testing.expectFmt("subs x7, sp, x8", "{f}", .{(try as.nextInstruction()).?});
1294 try std.testing.expectFmt("subs x9, sp, x9", "{f}", .{(try as.nextInstruction()).?});
1295 try std.testing.expectFmt("subs x10, x10, xzr", "{f}", .{(try as.nextInstruction()).?});
1296 try std.testing.expectFmt("subs x11, x12, xzr", "{f}", .{(try as.nextInstruction()).?});
1297 try std.testing.expectFmt("cmp x13, xzr", "{f}", .{(try as.nextInstruction()).?});
1298 try std.testing.expectFmt("subs x14, sp, xzr", "{f}", .{(try as.nextInstruction()).?});
1299 try std.testing.expectFmt("cmp sp, xzr", "{f}", .{(try as.nextInstruction()).?});
1300
1301 try std.testing.expectFmt("subs w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
1302 try std.testing.expectFmt("subs w2, w3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
1303 try std.testing.expectFmt("cmp w5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
1304 try std.testing.expectFmt("subs w7, wsp, w8, lsl #2", "{f}", .{(try as.nextInstruction()).?});
1305 try std.testing.expectFmt("subs w9, wsp, w9, uxtx", "{f}", .{(try as.nextInstruction()).?});
1306 try std.testing.expectFmt("subs w10, w10, wzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
1307 try std.testing.expectFmt("subs w11, w12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
1308 try std.testing.expectFmt("cmp w13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
1309 try std.testing.expectFmt("subs w14, wsp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
1310 try std.testing.expectFmt("cmp wsp, wzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
1311
1312 try std.testing.expectFmt("subs x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
1313 try std.testing.expectFmt("subs x2, x3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
1314 try std.testing.expectFmt("cmp x5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
1315 try std.testing.expectFmt("subs x7, sp, w8, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
1316 try std.testing.expectFmt("cmp sp, x9", "{f}", .{(try as.nextInstruction()).?});
1317 try std.testing.expectFmt("subs x10, x10, xzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
1318 try std.testing.expectFmt("subs x11, x12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
1319 try std.testing.expectFmt("cmp x13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
1320 try std.testing.expectFmt("subs x14, sp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
1321 try std.testing.expectFmt("cmp sp, xzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
1322
1323 try std.testing.expectFmt("subs w0, w0, #0x0", "{f}", .{(try as.nextInstruction()).?});
1324 try std.testing.expectFmt("subs w0, w1, #0x1", "{f}", .{(try as.nextInstruction()).?});
1325 try std.testing.expectFmt("subs wzr, w2, #0x2, lsl #12", "{f}", .{(try as.nextInstruction()).?});
1326 try std.testing.expectFmt("subs w3, wsp, #0x3", "{f}", .{(try as.nextInstruction()).?});
1327 try std.testing.expectFmt("subs wzr, wsp, #0xfff, lsl #12", "{f}", .{(try as.nextInstruction()).?});
1328 try std.testing.expectFmt("subs w0, w1, #0x0", "{f}", .{(try as.nextInstruction()).?});
1329 try std.testing.expectFmt("subs w2, w3, #0x0", "{f}", .{(try as.nextInstruction()).?});
1330 try std.testing.expectFmt("subs w4, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1331 try std.testing.expectFmt("subs w5, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1332 try std.testing.expectFmt("subs wzr, w6, #0x0", "{f}", .{(try as.nextInstruction()).?});
1333 try std.testing.expectFmt("subs wzr, w7, #0x0", "{f}", .{(try as.nextInstruction()).?});
1334 try std.testing.expectFmt("subs wzr, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1335 try std.testing.expectFmt("subs wzr, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1336
1337 try std.testing.expectFmt("subs x0, x0, #0x0", "{f}", .{(try as.nextInstruction()).?});
1338 try std.testing.expectFmt("subs x0, x1, #0x1", "{f}", .{(try as.nextInstruction()).?});
1339 try std.testing.expectFmt("subs xzr, x2, #0x2, lsl #12", "{f}", .{(try as.nextInstruction()).?});
1340 try std.testing.expectFmt("subs x3, sp, #0x3", "{f}", .{(try as.nextInstruction()).?});
1341 try std.testing.expectFmt("subs xzr, sp, #0xfff, lsl #12", "{f}", .{(try as.nextInstruction()).?});
1342 try std.testing.expectFmt("subs x0, x1, #0x0", "{f}", .{(try as.nextInstruction()).?});
1343 try std.testing.expectFmt("subs x2, x3, #0x0", "{f}", .{(try as.nextInstruction()).?});
1344 try std.testing.expectFmt("subs x4, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1345 try std.testing.expectFmt("subs x5, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1346 try std.testing.expectFmt("subs xzr, x6, #0x0", "{f}", .{(try as.nextInstruction()).?});
1347 try std.testing.expectFmt("subs xzr, x7, #0x0", "{f}", .{(try as.nextInstruction()).?});
1348 try std.testing.expectFmt("subs xzr, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1349 try std.testing.expectFmt("subs xzr, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
1350
1351 try std.testing.expectFmt("subs w0, w0, w0", "{f}", .{(try as.nextInstruction()).?});
1352 try std.testing.expectFmt("subs w1, w1, w2", "{f}", .{(try as.nextInstruction()).?});
1353 try std.testing.expectFmt("subs w3, w4, w5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
1354 try std.testing.expectFmt("subs w6, w6, wzr, lsl #31", "{f}", .{(try as.nextInstruction()).?});
1355 try std.testing.expectFmt("negs w7, w8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
1356 try std.testing.expectFmt("negs w9, wzr, lsr #30", "{f}", .{(try as.nextInstruction()).?});
1357 try std.testing.expectFmt("cmp w10, w11, lsr #31", "{f}", .{(try as.nextInstruction()).?});
1358 try std.testing.expectFmt("cmp w12, wzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
1359 try std.testing.expectFmt("cmp wzr, w13, asr #16", "{f}", .{(try as.nextInstruction()).?});
1360 try std.testing.expectFmt("cmp wzr, wzr, asr #31", "{f}", .{(try as.nextInstruction()).?});
1361
1362 try std.testing.expectFmt("subs x0, x0, x0", "{f}", .{(try as.nextInstruction()).?});
1363 try std.testing.expectFmt("subs x1, x1, x2", "{f}", .{(try as.nextInstruction()).?});
1364 try std.testing.expectFmt("subs x3, x4, x5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
1365 try std.testing.expectFmt("subs x6, x6, xzr, lsl #63", "{f}", .{(try as.nextInstruction()).?});
1366 try std.testing.expectFmt("negs x7, x8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
1367 try std.testing.expectFmt("negs x9, xzr, lsr #62", "{f}", .{(try as.nextInstruction()).?});
1368 try std.testing.expectFmt("cmp x10, x11, lsr #63", "{f}", .{(try as.nextInstruction()).?});
1369 try std.testing.expectFmt("cmp x12, xzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
1370 try std.testing.expectFmt("cmp xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
1371 try std.testing.expectFmt("cmp xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
8931372
8941373 try std.testing.expect(null == try as.nextInstruction());
8951374}
......@@ -966,44 +1445,62 @@ test "bit manipulation" {
9661445test "bitfield" {
9671446 var as: Assemble = .{
9681447 .source =
969 \\sbfm w0, w0, #0, #31
970 \\sbfm w0, w0, #31, #0
971 \\
972 \\sbfm x0, x0, #0, #63
973 \\sbfm x0, x0, #63, #0
974 \\
975 \\bfm w0, w0, #0, #31
976 \\bfm w0, w0, #31, #0
977 \\
978 \\bfm x0, x0, #0, #63
979 \\bfm x0, x0, #63, #0
980 \\
981 \\ubfm w0, w0, #0, #31
982 \\ubfm w0, w0, #31, #0
983 \\
984 \\ubfm x0, x0, #0, #63
985 \\ubfm x0, x0, #63, #0
1448 \\bfc w0, #1, #31
1449 \\bfc w1, #31, #1
1450 \\bfc x2, #1, #63
1451 \\bfc x3, #63, #1
1452 \\
1453 \\bfi w0, w1, #1, #31
1454 \\bfi w2, wzr, #31, #1
1455 \\bfi x3, xzr, #1, #63
1456 \\bfi x4, x5, #63, #1
1457 \\
1458 \\bfm w0, wzr, #25, #5
1459 \\bfm w1, w2, #31, #1
1460 \\bfm w3, w4, #1, #31
1461 \\bfm x5, xzr, #57, #7
1462 \\bfm x6, x7, #63, #1
1463 \\bfm x8, x9, #1, #63
1464 \\
1465 \\sbfm w0, w1, #31, #1
1466 \\sbfm w2, w3, #1, #31
1467 \\sbfm x4, x5, #63, #1
1468 \\sbfm x6, x7, #1, #63
1469 \\
1470 \\ubfm w0, w1, #31, #1
1471 \\ubfm w2, w3, #1, #31
1472 \\ubfm x4, x5, #63, #1
1473 \\ubfm x6, x7, #1, #63
9861474 ,
9871475 .operands = .empty,
9881476 };
9891477
990 try std.testing.expectFmt("sbfm w0, w0, #0, #31", "{f}", .{(try as.nextInstruction()).?});
991 try std.testing.expectFmt("sbfm w0, w0, #31, #0", "{f}", .{(try as.nextInstruction()).?});
992
993 try std.testing.expectFmt("sbfm x0, x0, #0, #63", "{f}", .{(try as.nextInstruction()).?});
994 try std.testing.expectFmt("sbfm x0, x0, #63, #0", "{f}", .{(try as.nextInstruction()).?});
995
996 try std.testing.expectFmt("bfm w0, w0, #0, #31", "{f}", .{(try as.nextInstruction()).?});
997 try std.testing.expectFmt("bfm w0, w0, #31, #0", "{f}", .{(try as.nextInstruction()).?});
998
999 try std.testing.expectFmt("bfm x0, x0, #0, #63", "{f}", .{(try as.nextInstruction()).?});
1000 try std.testing.expectFmt("bfm x0, x0, #63, #0", "{f}", .{(try as.nextInstruction()).?});
1001
1002 try std.testing.expectFmt("ubfm w0, w0, #0, #31", "{f}", .{(try as.nextInstruction()).?});
1003 try std.testing.expectFmt("ubfm w0, w0, #31, #0", "{f}", .{(try as.nextInstruction()).?});
1004
1005 try std.testing.expectFmt("ubfm x0, x0, #0, #63", "{f}", .{(try as.nextInstruction()).?});
1006 try std.testing.expectFmt("ubfm x0, x0, #63, #0", "{f}", .{(try as.nextInstruction()).?});
1478 try std.testing.expectFmt("bfc w0, #1, #31", "{f}", .{(try as.nextInstruction()).?});
1479 try std.testing.expectFmt("bfc w1, #31, #1", "{f}", .{(try as.nextInstruction()).?});
1480 try std.testing.expectFmt("bfc x2, #1, #63", "{f}", .{(try as.nextInstruction()).?});
1481 try std.testing.expectFmt("bfc x3, #63, #1", "{f}", .{(try as.nextInstruction()).?});
1482
1483 try std.testing.expectFmt("bfi w0, w1, #1, #31", "{f}", .{(try as.nextInstruction()).?});
1484 try std.testing.expectFmt("bfc w2, #31, #1", "{f}", .{(try as.nextInstruction()).?});
1485 try std.testing.expectFmt("bfc x3, #1, #63", "{f}", .{(try as.nextInstruction()).?});
1486 try std.testing.expectFmt("bfi x4, x5, #63, #1", "{f}", .{(try as.nextInstruction()).?});
1487
1488 try std.testing.expectFmt("bfc w0, #7, #6", "{f}", .{(try as.nextInstruction()).?});
1489 try std.testing.expectFmt("bfi w1, w2, #1, #2", "{f}", .{(try as.nextInstruction()).?});
1490 try std.testing.expectFmt("bfxil w3, w4, #1, #31", "{f}", .{(try as.nextInstruction()).?});
1491 try std.testing.expectFmt("bfc x5, #7, #8", "{f}", .{(try as.nextInstruction()).?});
1492 try std.testing.expectFmt("bfi x6, x7, #1, #2", "{f}", .{(try as.nextInstruction()).?});
1493 try std.testing.expectFmt("bfxil x8, x9, #1, #63", "{f}", .{(try as.nextInstruction()).?});
1494
1495 try std.testing.expectFmt("sbfiz w0, w1, #1, #2", "{f}", .{(try as.nextInstruction()).?});
1496 try std.testing.expectFmt("sbfx w2, w3, #1, #31", "{f}", .{(try as.nextInstruction()).?});
1497 try std.testing.expectFmt("sbfiz x4, x5, #1, #2", "{f}", .{(try as.nextInstruction()).?});
1498 try std.testing.expectFmt("sbfx x6, x7, #1, #63", "{f}", .{(try as.nextInstruction()).?});
1499
1500 try std.testing.expectFmt("ubfiz w0, w1, #1, #2", "{f}", .{(try as.nextInstruction()).?});
1501 try std.testing.expectFmt("ubfx w2, w3, #1, #31", "{f}", .{(try as.nextInstruction()).?});
1502 try std.testing.expectFmt("ubfiz x4, x5, #1, #2", "{f}", .{(try as.nextInstruction()).?});
1503 try std.testing.expectFmt("ubfx x6, x7, #1, #63", "{f}", .{(try as.nextInstruction()).?});
10071504
10081505 try std.testing.expect(null == try as.nextInstruction());
10091506}
......@@ -1113,6 +1610,22 @@ test "extract" {
11131610
11141611 try std.testing.expect(null == try as.nextInstruction());
11151612}
1613test "flags" {
1614 var as: Assemble = .{
1615 .source =
1616 \\AXFLAG
1617 \\CFINV
1618 \\XAFLAG
1619 ,
1620 .operands = .empty,
1621 };
1622
1623 try std.testing.expectFmt("axflag", "{f}", .{(try as.nextInstruction()).?});
1624 try std.testing.expectFmt("cfinv", "{f}", .{(try as.nextInstruction()).?});
1625 try std.testing.expectFmt("xaflag", "{f}", .{(try as.nextInstruction()).?});
1626
1627 try std.testing.expect(null == try as.nextInstruction());
1628}
11161629test "hints" {
11171630 var as: Assemble = .{
11181631 .source =
......@@ -2935,6 +3448,5 @@ const aarch64 = @import("../aarch64.zig");
29353448const Assemble = @This();
29363449const assert = std.debug.assert;
29373450const Instruction = aarch64.encoding.Instruction;
2938const instructions = @import("instructions.zon");
29393451const std = @import("std");
29403452const log = std.log.scoped(.@"asm");
src/codegen/aarch64/Disassemble.zig+96-16
......@@ -80,7 +80,22 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr
8080 @tagName(sh),
8181 });
8282 },
83 .add_subtract_immediate_with_tags => {},
83 .add_subtract_immediate_with_tags => |add_subtract_immediate_with_tags| {
84 const decoded = add_subtract_immediate_with_tags.decode();
85 if (decoded == .unallocated) break :unallocated;
86 const group = add_subtract_immediate_with_tags.group;
87 return writer.print("{f}{s}{f}{s}{f}{s}#0x{x}{s}#0x{x}", .{
88 fmtCase(decoded, dis.case),
89 dis.mnemonic_operands_separator,
90 group.Rd.decode(.{ .sp = true }).x().fmtCase(dis.case),
91 dis.operands_separator,
92 group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
93 dis.operands_separator,
94 @as(u10, group.uimm6) << 4,
95 dis.operands_separator,
96 group.uimm4,
97 });
98 },
8499 .logical_immediate => |logical_immediate| {
85100 const decoded = logical_immediate.decode();
86101 if (decoded == .unallocated) break :unallocated;
......@@ -172,17 +187,69 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr
172187 if (decoded == .unallocated) break :unallocated;
173188 const group = bitfield.group;
174189 const sf = group.sf;
175 return writer.print("{f}{s}{f}{s}{f}{s}#{d}{s}#{d}", .{
190 const Rd = group.Rd.decode(.{}).general(sf);
191 const Rn = group.Rn.decode(.{}).general(sf);
192 return if (!dis.enable_aliases) writer.print("{f}{s}{f}{s}{f}{s}#{d}{s}#{d}", .{
176193 fmtCase(decoded, dis.case),
177194 dis.mnemonic_operands_separator,
178 group.Rd.decode(.{}).general(sf).fmtCase(dis.case),
195 Rd.fmtCase(dis.case),
179196 dis.operands_separator,
180 group.Rn.decode(.{}).general(sf).fmtCase(dis.case),
197 Rn.fmtCase(dis.case),
181198 dis.operands_separator,
182199 group.imm.immr,
183200 dis.operands_separator,
184201 group.imm.imms,
185 });
202 }) else if (group.imm.imms >= group.imm.immr) writer.print("{f}{s}{f}{s}{f}{s}#{d}{s}#{d}", .{
203 fmtCase(@as(enum { sbfx, bfxil, ubfx }, switch (decoded) {
204 .unallocated => unreachable,
205 .sbfm => .sbfx,
206 .bfm => .bfxil,
207 .ubfm => .ubfx,
208 }), dis.case),
209 dis.mnemonic_operands_separator,
210 Rd.fmtCase(dis.case),
211 dis.operands_separator,
212 Rn.fmtCase(dis.case),
213 dis.operands_separator,
214 group.imm.immr,
215 dis.operands_separator,
216 switch (sf) {
217 .word => @as(u6, group.imm.imms - group.imm.immr) + 1,
218 .doubleword => @as(u7, group.imm.imms - group.imm.immr) + 1,
219 },
220 }) else {
221 const prefer_bfc = switch (decoded) {
222 .unallocated => unreachable,
223 .sbfm, .ubfm => false,
224 .bfm => Rn.alias == .zr,
225 };
226 try writer.print("{f}{s}{f}", .{
227 fmtCase(@as(enum { sbfiz, bfc, bfi, ubfiz }, switch (decoded) {
228 .unallocated => unreachable,
229 .sbfm => .sbfiz,
230 .bfm => if (prefer_bfc) .bfc else .bfi,
231 .ubfm => .ubfiz,
232 }), dis.case),
233 dis.mnemonic_operands_separator,
234 Rd.fmtCase(dis.case),
235 });
236 if (!prefer_bfc) try writer.print("{s}{f}", .{
237 dis.operands_separator,
238 Rn.fmtCase(dis.case),
239 });
240 try writer.print("{s}#{d}{s}#{d}", .{
241 dis.operands_separator,
242 switch (sf) {
243 .word => -%@as(u5, @intCast(group.imm.immr)),
244 .doubleword => -%@as(u6, @intCast(group.imm.immr)),
245 },
246 dis.operands_separator,
247 switch (sf) {
248 .word => @as(u6, group.imm.imms) + 1,
249 .doubleword => @as(u7, group.imm.imms) + 1,
250 },
251 });
252 };
186253 },
187254 .extract => |extract| {
188255 const decoded = extract.decode();
......@@ -249,7 +316,11 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr
249316 else => |decoded| return writer.print("{f}", .{fmtCase(decoded, dis.case)}),
250317 },
251318 .barriers => {},
252 .pstate => {},
319 .pstate => |pstate| {
320 const decoded = pstate.decode();
321 if (decoded == .unallocated) break :unallocated;
322 return writer.print("{f}", .{fmtCase(decoded, dis.case)});
323 },
253324 .system_result => {},
254325 .system => {},
255326 .system_register_move => {},
......@@ -695,9 +766,19 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr
695766 if (decoded == .unallocated) break :unallocated;
696767 const group = add_subtract_extended_register.group;
697768 const sf = group.sf;
698 const Rm = group.Rm.decode(.{}).general(group.option.sf());
769 const Rm = group.Rm.decode(.{}).general(switch (sf) {
770 .word => .word,
771 .doubleword => group.option.sf(),
772 });
699773 const Rn = group.Rn.decode(.{ .sp = true }).general(sf);
700 const Rd = group.Rd.decode(.{ .sp = true }).general(sf);
774 const Rd = group.Rd.decode(.{ .sp = !group.S }).general(sf);
775 const prefer_lsl = (Rd.alias == .sp or Rn.alias == .sp) and group.option == @as(
776 aarch64.encoding.Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option,
777 switch (sf) {
778 .word => .uxtw,
779 .doubleword => .uxtx,
780 },
781 );
701782 if (dis.enable_aliases and group.S and Rd.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
702783 fmtCase(@as(enum { cmn, cmp }, switch (group.op) {
703784 .add => .cmn,
......@@ -716,14 +797,13 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr
716797 dis.operands_separator,
717798 Rm.fmtCase(dis.case),
718799 });
719 return if (group.option != @as(aarch64.encoding.Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option, switch (sf) {
720 .word => .uxtw,
721 .doubleword => .uxtx,
722 }) or group.imm3 != 0) writer.print("{s}{f} #{d}", .{
723 dis.operands_separator,
724 fmtCase(group.option, dis.case),
725 group.imm3,
726 });
800 return if (!prefer_lsl or group.imm3 != 0) {
801 try writer.print("{s}{f}", .{
802 dis.operands_separator,
803 if (prefer_lsl) fmtCase(.lsl, dis.case) else fmtCase(group.option, dis.case),
804 });
805 if (group.imm3 != 0) try writer.print(" #{d}", .{group.imm3});
806 };
727807 },
728808 .add_subtract_with_carry => |add_subtract_with_carry| {
729809 const decoded = add_subtract_with_carry.decode();
src/codegen/aarch64/encoding.zig+63-4
......@@ -2563,6 +2563,10 @@ pub const Instruction = packed union {
25632563 /// PSTATE
25642564 pub const Pstate = packed union {
25652565 group: @This().Group,
2566 msr: Msr,
2567 cfinv: Cfinv,
2568 xaflag: Xaflag,
2569 axflag: Axflag,
25662570
25672571 pub const Group = packed struct {
25682572 Rt: Register.Encoded,
......@@ -2615,6 +2619,7 @@ pub const Instruction = packed union {
26152619
26162620 pub const Decoded = union(enum) {
26172621 unallocated,
2622 msr: Msr,
26182623 cfinv: Cfinv,
26192624 xaflag: Xaflag,
26202625 axflag: Axflag,
......@@ -11414,7 +11419,10 @@ pub const Instruction = packed union {
1141411419 assert(n.format.general == sf);
1141511420 form: switch (form) {
1141611421 .extended_register_explicit => |extended_register_explicit| {
11417 assert(extended_register_explicit.register.format.general == extended_register_explicit.option.sf());
11422 assert(extended_register_explicit.register.format.general == switch (sf) {
11423 .word => .word,
11424 .doubleword => extended_register_explicit.option.sf(),
11425 });
1141811426 return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
1141911427 .add = .{
1142011428 .Rd = d.alias.encode(.{ .sp = true }),
......@@ -11484,6 +11492,18 @@ pub const Instruction = packed union {
1148411492 } },
1148511493 }
1148611494 }
11495 /// C7.2.6 ADDG
11496 pub fn addg(d: Register, n: Register, uimm6: u10, uimm4: u4) Instruction {
11497 assert(d.format.general == .doubleword and n.format.general == .doubleword);
11498 return .{ .data_processing_immediate = .{ .add_subtract_immediate_with_tags = .{
11499 .addg = .{
11500 .Xd = d.alias.encode(.{ .sp = true }),
11501 .Xn = n.alias.encode(.{ .sp = true }),
11502 .uimm4 = uimm4,
11503 .uimm6 = @intCast(@shrExact(uimm6, 4)),
11504 },
11505 } } };
11506 }
1148711507 /// C7.2.4 ADDP (scalar)
1148811508 /// C7.2.5 ADDP (vector)
1148911509 pub fn addp(d: Register, n: Register, form: union(enum) {
......@@ -11536,7 +11556,10 @@ pub const Instruction = packed union {
1153611556 assert(n.format.general == sf);
1153711557 form: switch (form) {
1153811558 .extended_register_explicit => |extended_register_explicit| {
11539 assert(extended_register_explicit.register.format.general == extended_register_explicit.option.sf());
11559 assert(extended_register_explicit.register.format.general == switch (sf) {
11560 .word => .word,
11561 .doubleword => extended_register_explicit.option.sf(),
11562 });
1154011563 return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
1154111564 .adds = .{
1154211565 .Rd = d.alias.encode(.{}),
......@@ -11768,6 +11791,12 @@ pub const Instruction = packed union {
1176811791 },
1176911792 } } };
1177011793 }
11794 /// C6.2.24 AXFLAG
11795 pub fn axflag() Instruction {
11796 return .{ .branch_exception_generating_system = .{ .pstate = .{
11797 .axflag = .{},
11798 } } };
11799 }
1177111800 /// C6.2.25 B
1177211801 pub fn b(label: i28) Instruction {
1177311802 return .{ .branch_exception_generating_system = .{ .unconditional_branch_immediate = .{
......@@ -12066,6 +12095,12 @@ pub const Instruction = packed union {
1206612095 } } },
1206712096 }
1206812097 }
12098 /// C6.2.52 CFINV
12099 pub fn cfinv() Instruction {
12100 return .{ .branch_exception_generating_system = .{ .pstate = .{
12101 .cfinv = .{},
12102 } } };
12103 }
1206912104 /// C6.2.56 CLREX
1207012105 pub fn clrex(imm: u4) Instruction {
1207112106 return .{ .branch_exception_generating_system = .{ .barriers = .{
......@@ -16057,7 +16092,10 @@ pub const Instruction = packed union {
1605716092 assert(n.format.general == sf);
1605816093 form: switch (form) {
1605916094 .extended_register_explicit => |extended_register_explicit| {
16060 assert(extended_register_explicit.register.format.general == extended_register_explicit.option.sf());
16095 assert(extended_register_explicit.register.format.general == switch (sf) {
16096 .word => .word,
16097 .doubleword => extended_register_explicit.option.sf(),
16098 });
1606116099 return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
1606216100 .sub = .{
1606316101 .Rd = d.alias.encode(.{ .sp = true }),
......@@ -16127,6 +16165,18 @@ pub const Instruction = packed union {
1612716165 } },
1612816166 }
1612916167 }
16168 /// C7.2.359 SUBG
16169 pub fn subg(d: Register, n: Register, uimm6: u10, uimm4: u4) Instruction {
16170 assert(d.format.general == .doubleword and n.format.general == .doubleword);
16171 return .{ .data_processing_immediate = .{ .add_subtract_immediate_with_tags = .{
16172 .subg = .{
16173 .Xd = d.alias.encode(.{ .sp = true }),
16174 .Xn = n.alias.encode(.{ .sp = true }),
16175 .uimm4 = uimm4,
16176 .uimm6 = @intCast(@shrExact(uimm6, 4)),
16177 },
16178 } } };
16179 }
1613016180 /// C6.2.362 SUBS (extended register)
1613116181 /// C6.2.363 SUBS (immediate)
1613216182 /// C6.2.364 SUBS (shifted register)
......@@ -16147,7 +16197,10 @@ pub const Instruction = packed union {
1614716197 assert(n.format.general == sf);
1614816198 form: switch (form) {
1614916199 .extended_register_explicit => |extended_register_explicit| {
16150 assert(extended_register_explicit.register.format.general == extended_register_explicit.option.sf());
16200 assert(extended_register_explicit.register.format.general == switch (sf) {
16201 .word => .word,
16202 .doubleword => extended_register_explicit.option.sf(),
16203 });
1615116204 return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
1615216205 .subs = .{
1615316206 .Rd = d.alias.encode(.{}),
......@@ -16471,6 +16524,12 @@ pub const Instruction = packed union {
1647116524 .wfi = .{},
1647216525 } } };
1647316526 }
16527 /// C6.2.400 XAFLAG
16528 pub fn xaflag() Instruction {
16529 return .{ .branch_exception_generating_system = .{ .pstate = .{
16530 .xaflag = .{},
16531 } } };
16532 }
1647416533 /// C6.2.402 YIELD
1647516534 pub fn yield() Instruction {
1647616535 return .{ .branch_exception_generating_system = .{ .hints = .{
src/codegen/aarch64/instructions.zon+635-2
......@@ -1,4 +1,42 @@
11.{
2 // C6.2.1 ADC
3 .{
4 .pattern = "ADC <Wd>, <Wn>, <Wm>",
5 .symbols = .{
6 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
7 .Wn = .{ .reg = .{ .format = .{ .general = .word } } },
8 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
9 },
10 .encode = .{ .adc, .Wd, .Wn, .Wm },
11 },
12 .{
13 .pattern = "ADC <Xd>, <Xn>, <Xm>",
14 .symbols = .{
15 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
16 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
17 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
18 },
19 .encode = .{ .adc, .Xd, .Xn, .Xm },
20 },
21 // C6.2.2 ADCS
22 .{
23 .pattern = "ADCS <Wd>, <Wn>, <Wm>",
24 .symbols = .{
25 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
26 .Wn = .{ .reg = .{ .format = .{ .general = .word } } },
27 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
28 },
29 .encode = .{ .adcs, .Wd, .Wn, .Wm },
30 },
31 .{
32 .pattern = "ADCS <Xd>, <Xn>, <Xm>",
33 .symbols = .{
34 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
35 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
36 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
37 },
38 .encode = .{ .adcs, .Xd, .Xn, .Xm },
39 },
240 // C6.2.3 ADD (extended register)
341 .{
442 .pattern = "ADD <Wd|WSP>, <Wn|WSP>, <Wm>",
......@@ -9,13 +47,27 @@
947 },
1048 .encode = .{ .add, .Wd, .Wn, .{ .register = .Wm } },
1149 },
50 .{
51 .pattern = "ADD <Wd|WSP>, <Wn|WSP>, <Wm>, <extend>",
52 .symbols = .{
53 .Wd = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
54 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
55 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
56 .extend = .{ .extend = .{} },
57 },
58 .encode = .{ .add, .Wd, .Wn, .{ .extended_register_explicit = .{
59 .register = .Wm,
60 .option = .extend,
61 .amount = 0,
62 } } },
63 },
1264 .{
1365 .pattern = "ADD <Wd|WSP>, <Wn|WSP>, <Wm>, <extend> #<amount>",
1466 .symbols = .{
1567 .Wd = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
1668 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
1769 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
18 .extend = .{ .extend = .{ .size = .word } },
70 .extend = .{ .extend = .{} },
1971 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
2072 },
2173 .encode = .{ .add, .Wd, .Wn, .{ .extended_register_explicit = .{
......@@ -33,6 +85,20 @@
3385 },
3486 .encode = .{ .add, .Xd, .Xn, .{ .register = .Xm } },
3587 },
88 .{
89 .pattern = "ADD <Xd|SP>, <Xn|SP>, <Wm>, <extend>",
90 .symbols = .{
91 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
92 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
93 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
94 .extend = .{ .extend = .{ .size = .word } },
95 },
96 .encode = .{ .add, .Xd, .Xn, .{ .extended_register_explicit = .{
97 .register = .Wm,
98 .option = .extend,
99 .amount = 0,
100 } } },
101 },
36102 .{
37103 .pattern = "ADD <Xd|SP>, <Xn|SP>, <Wm>, <extend> #<amount>",
38104 .symbols = .{
......@@ -48,6 +114,20 @@
48114 .amount = .amount,
49115 } } },
50116 },
117 .{
118 .pattern = "ADD <Xd|SP>, <Xn|SP>, <Xm>, <extend>",
119 .symbols = .{
120 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
121 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
122 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
123 .extend = .{ .extend = .{ .size = .doubleword } },
124 },
125 .encode = .{ .add, .Xd, .Xn, .{ .extended_register_explicit = .{
126 .register = .Xm,
127 .option = .extend,
128 .amount = 0,
129 } } },
130 },
51131 .{
52132 .pattern = "ADD <Xd|SP>, <Xn|SP>, <Xm>, <extend> #<amount>",
53133 .symbols = .{
......@@ -151,6 +231,212 @@
151231 .amount = .amount,
152232 } } },
153233 },
234 // C6.2.6 ADDG
235 .{
236 .requires = .{.mte},
237 .pattern = "ADDG <Xd|SP>, <Xn|SP>, #<uimm6>, #<uimm4>",
238 .symbols = .{
239 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
240 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
241 .uimm6 = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 10 }, .multiple_of = 16 } },
242 .uimm4 = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 } } },
243 },
244 .encode = .{ .addg, .Xd, .Xn, .uimm6, .uimm4 },
245 },
246 // C6.2.7 ADDS (extended register)
247 .{
248 .pattern = "ADDS <Wd>, <Wn|WSP>, <Wm>",
249 .symbols = .{
250 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
251 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
252 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
253 },
254 .encode = .{ .adds, .Wd, .Wn, .{ .register = .Wm } },
255 },
256 .{
257 .pattern = "ADDS <Wd>, <Wn|WSP>, <Wm>, <extend>",
258 .symbols = .{
259 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
260 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
261 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
262 .extend = .{ .extend = .{} },
263 },
264 .encode = .{ .adds, .Wd, .Wn, .{ .extended_register_explicit = .{
265 .register = .Wm,
266 .option = .extend,
267 .amount = 0,
268 } } },
269 },
270 .{
271 .pattern = "ADDS <Wd>, <Wn|WSP>, <Wm>, <extend> #<amount>",
272 .symbols = .{
273 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
274 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
275 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
276 .extend = .{ .extend = .{} },
277 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
278 },
279 .encode = .{ .adds, .Wd, .Wn, .{ .extended_register_explicit = .{
280 .register = .Wm,
281 .option = .extend,
282 .amount = .amount,
283 } } },
284 },
285 .{
286 .pattern = "ADDS <Xd>, <Xn|SP>, <Xm>",
287 .symbols = .{
288 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
289 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
290 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
291 },
292 .encode = .{ .adds, .Xd, .Xn, .{ .register = .Xm } },
293 },
294 .{
295 .pattern = "ADDS <Xd>, <Xn|SP>, <Wm>, <extend>",
296 .symbols = .{
297 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
298 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
299 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
300 .extend = .{ .extend = .{ .size = .word } },
301 },
302 .encode = .{ .adds, .Xd, .Xn, .{ .extended_register_explicit = .{
303 .register = .Wm,
304 .option = .extend,
305 .amount = 0,
306 } } },
307 },
308 .{
309 .pattern = "ADDS <Xd>, <Xn|SP>, <Wm>, <extend> #<amount>",
310 .symbols = .{
311 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
312 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
313 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
314 .extend = .{ .extend = .{ .size = .word } },
315 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
316 },
317 .encode = .{ .adds, .Xd, .Xn, .{ .extended_register_explicit = .{
318 .register = .Wm,
319 .option = .extend,
320 .amount = .amount,
321 } } },
322 },
323 .{
324 .pattern = "ADDS <Xd>, <Xn|SP>, <Xm>, <extend>",
325 .symbols = .{
326 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
327 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
328 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
329 .extend = .{ .extend = .{ .size = .doubleword } },
330 },
331 .encode = .{ .adds, .Xd, .Xn, .{ .extended_register_explicit = .{
332 .register = .Xm,
333 .option = .extend,
334 .amount = 0,
335 } } },
336 },
337 .{
338 .pattern = "ADDS <Xd>, <Xn|SP>, <Xm>, <extend> #<amount>",
339 .symbols = .{
340 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
341 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
342 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
343 .extend = .{ .extend = .{ .size = .doubleword } },
344 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
345 },
346 .encode = .{ .adds, .Xd, .Xn, .{ .extended_register_explicit = .{
347 .register = .Xm,
348 .option = .extend,
349 .amount = .amount,
350 } } },
351 },
352 // C6.2.8 ADDS (immediate)
353 .{
354 .pattern = "ADDS <Wd>, <Wn|WSP>, #<imm>",
355 .symbols = .{
356 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
357 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
358 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
359 },
360 .encode = .{ .adds, .Wd, .Wn, .{ .immediate = .imm } },
361 },
362 .{
363 .pattern = "ADDS <Wd>, <Wn|WSP>, #<imm>, LSL #<shift>",
364 .symbols = .{
365 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
366 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
367 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
368 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 }, .multiple_of = 12 } },
369 },
370 .encode = .{ .adds, .Wd, .Wn, .{ .shifted_immediate = .{ .immediate = .imm, .lsl = .shift } } },
371 },
372 .{
373 .pattern = "ADDS <Xd>, <Xn|SP>, #<imm>",
374 .symbols = .{
375 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
376 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
377 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
378 },
379 .encode = .{ .adds, .Xd, .Xn, .{ .immediate = .imm } },
380 },
381 .{
382 .pattern = "ADDS <Xd>, <Xn|SP>, #<imm>, LSL #<shift>",
383 .symbols = .{
384 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
385 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
386 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
387 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 }, .multiple_of = 12 } },
388 },
389 .encode = .{ .adds, .Xd, .Xn, .{ .shifted_immediate = .{ .immediate = .imm, .lsl = .shift } } },
390 },
391 // C6.2.9 ADDS (shifted register)
392 .{
393 .pattern = "ADDS <Wd>, <Wn>, <Wm>",
394 .symbols = .{
395 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
396 .Wn = .{ .reg = .{ .format = .{ .general = .word } } },
397 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
398 },
399 .encode = .{ .adds, .Wd, .Wn, .{ .register = .Wm } },
400 },
401 .{
402 .pattern = "ADDS <Wd>, <Wn>, <Wm>, <shift> #<amount>",
403 .symbols = .{
404 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
405 .Wn = .{ .reg = .{ .format = .{ .general = .word } } },
406 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
407 .shift = .{ .shift = .{ .allow_ror = false } },
408 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
409 },
410 .encode = .{ .adds, .Wd, .Wn, .{ .shifted_register_explicit = .{
411 .register = .Wm,
412 .shift = .shift,
413 .amount = .amount,
414 } } },
415 },
416 .{
417 .pattern = "ADDS <Xd>, <Xn>, <Xm>",
418 .symbols = .{
419 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
420 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
421 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
422 },
423 .encode = .{ .adds, .Xd, .Xn, .{ .register = .Xm } },
424 },
425 .{
426 .pattern = "ADDS <Xd>, <Xn>, <Xm>, <shift> #<amount>",
427 .symbols = .{
428 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
429 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
430 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
431 .shift = .{ .shift = .{ .allow_ror = false } },
432 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
433 },
434 .encode = .{ .adds, .Xd, .Xn, .{ .shifted_register_explicit = .{
435 .register = .Xm,
436 .shift = .shift,
437 .amount = .amount,
438 } } },
439 },
154440 // C6.2.13 AND (shifted register)
155441 .{
156442 .pattern = "AND <Wd>, <Wn>, <Wm>",
......@@ -306,6 +592,53 @@
306592 },
307593 .encode = .{ .asrv, .Xd, .Xn, .Xm },
308594 },
595 // C6.2.24 AXFLAG
596 .{
597 .requires = .{.altnzcv},
598 .pattern = "AXFLAG",
599 .symbols = .{},
600 .encode = .{.axflag},
601 },
602 // C6.2.28 BFC
603 .{
604 .pattern = "BFC <Wd>, #<lsb>, #<width>",
605 .symbols = .{
606 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
607 .lsb = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 }, .adjust = .neg_wrap } },
608 .width = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 }, .adjust = .dec } },
609 },
610 .encode = .{ .bfm, .Wd, .wzr, .{ .N = .word, .immr = .lsb, .imms = .width } },
611 },
612 .{
613 .pattern = "BFC <Xd>, #<lsb>, #<width>",
614 .symbols = .{
615 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
616 .lsb = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 }, .adjust = .neg_wrap } },
617 .width = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 }, .adjust = .dec } },
618 },
619 .encode = .{ .bfm, .Xd, .xzr, .{ .N = .doubleword, .immr = .lsb, .imms = .width } },
620 },
621 // C6.2.29 BFI
622 .{
623 .pattern = "BFI <Wd>, <Wn>, #<lsb>, #<width>",
624 .symbols = .{
625 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
626 .Wn = .{ .reg = .{ .format = .{ .general = .word } } },
627 .lsb = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 }, .adjust = .neg_wrap } },
628 .width = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 }, .adjust = .dec } },
629 },
630 .encode = .{ .bfm, .Wd, .Wn, .{ .N = .word, .immr = .lsb, .imms = .width } },
631 },
632 .{
633 .pattern = "BFI <Xd>, <Xn>, #<lsb>, #<width>",
634 .symbols = .{
635 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
636 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
637 .lsb = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 }, .adjust = .neg_wrap } },
638 .width = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 }, .adjust = .dec } },
639 },
640 .encode = .{ .bfm, .Xd, .Xn, .{ .N = .doubleword, .immr = .lsb, .imms = .width } },
641 },
309642 // C6.2.30 BFM
310643 .{
311644 .pattern = "BFM <Wd>, <Wn>, #<immr>, #<imms>",
......@@ -351,6 +684,13 @@
351684 },
352685 .encode = .{ .brk, .imm },
353686 },
687 // C6.2.52 CFINV
688 .{
689 .requires = .{.flagm},
690 .pattern = "CFINV",
691 .symbols = .{},
692 .encode = .{.cfinv},
693 },
354694 // C6.2.56 CLREX
355695 .{
356696 .pattern = "CLREX",
......@@ -1391,6 +1731,44 @@
13911731 },
13921732 .encode = .{ .rorv, .Xd, .Xn, .Xm },
13931733 },
1734 // C6.2.265 SBC
1735 .{
1736 .pattern = "SBC <Wd>, <Wn>, <Wm>",
1737 .symbols = .{
1738 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
1739 .Wn = .{ .reg = .{ .format = .{ .general = .word } } },
1740 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
1741 },
1742 .encode = .{ .sbc, .Wd, .Wn, .Wm },
1743 },
1744 .{
1745 .pattern = "SBC <Xd>, <Xn>, <Xm>",
1746 .symbols = .{
1747 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
1748 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
1749 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
1750 },
1751 .encode = .{ .sbc, .Xd, .Xn, .Xm },
1752 },
1753 // C6.2.266 SBCS
1754 .{
1755 .pattern = "SBCS <Wd>, <Wn>, <Wm>",
1756 .symbols = .{
1757 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
1758 .Wn = .{ .reg = .{ .format = .{ .general = .word } } },
1759 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
1760 },
1761 .encode = .{ .sbcs, .Wd, .Wn, .Wm },
1762 },
1763 .{
1764 .pattern = "SBCS <Xd>, <Xn>, <Xm>",
1765 .symbols = .{
1766 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
1767 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
1768 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
1769 },
1770 .encode = .{ .sbcs, .Xd, .Xn, .Xm },
1771 },
13941772 // C6.2.268 SBFM
13951773 .{
13961774 .pattern = "SBFM <Wd>, <Wn>, #<immr>, #<imms>",
......@@ -1663,13 +2041,27 @@
16632041 },
16642042 .encode = .{ .sub, .Wd, .Wn, .{ .register = .Wm } },
16652043 },
2044 .{
2045 .pattern = "SUB <Wd|WSP>, <Wn|WSP>, <Wm>, <extend>",
2046 .symbols = .{
2047 .Wd = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
2048 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
2049 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
2050 .extend = .{ .extend = .{} },
2051 },
2052 .encode = .{ .sub, .Wd, .Wn, .{ .extended_register_explicit = .{
2053 .register = .Wm,
2054 .option = .extend,
2055 .amount = 0,
2056 } } },
2057 },
16662058 .{
16672059 .pattern = "SUB <Wd|WSP>, <Wn|WSP>, <Wm>, <extend> #<amount>",
16682060 .symbols = .{
16692061 .Wd = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
16702062 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
16712063 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
1672 .extend = .{ .extend = .{ .size = .word } },
2064 .extend = .{ .extend = .{} },
16732065 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
16742066 },
16752067 .encode = .{ .sub, .Wd, .Wn, .{ .extended_register_explicit = .{
......@@ -1687,6 +2079,20 @@
16872079 },
16882080 .encode = .{ .sub, .Xd, .Xn, .{ .register = .Xm } },
16892081 },
2082 .{
2083 .pattern = "SUB <Xd|SP>, <Xn|SP>, <Wm>, <extend>",
2084 .symbols = .{
2085 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2086 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2087 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
2088 .extend = .{ .extend = .{ .size = .word } },
2089 },
2090 .encode = .{ .sub, .Xd, .Xn, .{ .extended_register_explicit = .{
2091 .register = .Wm,
2092 .option = .extend,
2093 .amount = 0,
2094 } } },
2095 },
16902096 .{
16912097 .pattern = "SUB <Xd|SP>, <Xn|SP>, <Wm>, <extend> #<amount>",
16922098 .symbols = .{
......@@ -1702,6 +2108,20 @@
17022108 .amount = .amount,
17032109 } } },
17042110 },
2111 .{
2112 .pattern = "SUB <Xd|SP>, <Xn|SP>, <Xm>, <extend>",
2113 .symbols = .{
2114 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2115 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2116 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2117 .extend = .{ .extend = .{ .size = .doubleword } },
2118 },
2119 .encode = .{ .sub, .Xd, .Xn, .{ .extended_register_explicit = .{
2120 .register = .Xm,
2121 .option = .extend,
2122 .amount = 0,
2123 } } },
2124 },
17052125 .{
17062126 .pattern = "SUB <Xd|SP>, <Xn|SP>, <Xm>, <extend> #<amount>",
17072127 .symbols = .{
......@@ -1805,6 +2225,212 @@
18052225 .amount = .amount,
18062226 } } },
18072227 },
2228 // C6.2.359 SUBG
2229 .{
2230 .requires = .{.mte},
2231 .pattern = "SUBG <Xd|SP>, <Xn|SP>, #<uimm6>, #<uimm4>",
2232 .symbols = .{
2233 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2234 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2235 .uimm6 = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 10 }, .multiple_of = 16 } },
2236 .uimm4 = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 } } },
2237 },
2238 .encode = .{ .subg, .Xd, .Xn, .uimm6, .uimm4 },
2239 },
2240 // C6.2.362 SUBS (extended register)
2241 .{
2242 .pattern = "SUBS <Wd>, <Wn|WSP>, <Wm>",
2243 .symbols = .{
2244 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
2245 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
2246 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
2247 },
2248 .encode = .{ .subs, .Wd, .Wn, .{ .register = .Wm } },
2249 },
2250 .{
2251 .pattern = "SUBS <Wd>, <Wn|WSP>, <Wm>, <extend>",
2252 .symbols = .{
2253 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
2254 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
2255 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
2256 .extend = .{ .extend = .{} },
2257 },
2258 .encode = .{ .subs, .Wd, .Wn, .{ .extended_register_explicit = .{
2259 .register = .Wm,
2260 .option = .extend,
2261 .amount = 0,
2262 } } },
2263 },
2264 .{
2265 .pattern = "SUBS <Wd>, <Wn|WSP>, <Wm>, <extend> #<amount>",
2266 .symbols = .{
2267 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
2268 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
2269 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
2270 .extend = .{ .extend = .{} },
2271 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
2272 },
2273 .encode = .{ .subs, .Wd, .Wn, .{ .extended_register_explicit = .{
2274 .register = .Wm,
2275 .option = .extend,
2276 .amount = .amount,
2277 } } },
2278 },
2279 .{
2280 .pattern = "SUBS <Xd>, <Xn|SP>, <Xm>",
2281 .symbols = .{
2282 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2283 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2284 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2285 },
2286 .encode = .{ .subs, .Xd, .Xn, .{ .register = .Xm } },
2287 },
2288 .{
2289 .pattern = "SUBS <Xd>, <Xn|SP>, <Wm>, <extend>",
2290 .symbols = .{
2291 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2292 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2293 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
2294 .extend = .{ .extend = .{ .size = .word } },
2295 },
2296 .encode = .{ .subs, .Xd, .Xn, .{ .extended_register_explicit = .{
2297 .register = .Wm,
2298 .option = .extend,
2299 .amount = 0,
2300 } } },
2301 },
2302 .{
2303 .pattern = "SUBS <Xd>, <Xn|SP>, <Wm>, <extend> #<amount>",
2304 .symbols = .{
2305 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2306 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2307 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
2308 .extend = .{ .extend = .{ .size = .word } },
2309 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
2310 },
2311 .encode = .{ .subs, .Xd, .Xn, .{ .extended_register_explicit = .{
2312 .register = .Wm,
2313 .option = .extend,
2314 .amount = .amount,
2315 } } },
2316 },
2317 .{
2318 .pattern = "SUBS <Xd>, <Xn|SP>, <Xm>, <extend>",
2319 .symbols = .{
2320 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2321 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2322 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2323 .extend = .{ .extend = .{ .size = .doubleword } },
2324 },
2325 .encode = .{ .subs, .Xd, .Xn, .{ .extended_register_explicit = .{
2326 .register = .Xm,
2327 .option = .extend,
2328 .amount = 0,
2329 } } },
2330 },
2331 .{
2332 .pattern = "SUBS <Xd>, <Xn|SP>, <Xm>, <extend> #<amount>",
2333 .symbols = .{
2334 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2335 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2336 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2337 .extend = .{ .extend = .{ .size = .doubleword } },
2338 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
2339 },
2340 .encode = .{ .subs, .Xd, .Xn, .{ .extended_register_explicit = .{
2341 .register = .Xm,
2342 .option = .extend,
2343 .amount = .amount,
2344 } } },
2345 },
2346 // C6.2.363 SUBS (immediate)
2347 .{
2348 .pattern = "SUBS <Wd>, <Wn|WSP>, #<imm>",
2349 .symbols = .{
2350 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
2351 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
2352 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
2353 },
2354 .encode = .{ .subs, .Wd, .Wn, .{ .immediate = .imm } },
2355 },
2356 .{
2357 .pattern = "SUBS <Wd>, <Wn|WSP>, #<imm>, LSL #<shift>",
2358 .symbols = .{
2359 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
2360 .Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
2361 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
2362 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 }, .multiple_of = 12 } },
2363 },
2364 .encode = .{ .subs, .Wd, .Wn, .{ .shifted_immediate = .{ .immediate = .imm, .lsl = .shift } } },
2365 },
2366 .{
2367 .pattern = "SUBS <Xd>, <Xn|SP>, #<imm>",
2368 .symbols = .{
2369 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2370 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2371 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
2372 },
2373 .encode = .{ .subs, .Xd, .Xn, .{ .immediate = .imm } },
2374 },
2375 .{
2376 .pattern = "SUBS <Xd>, <Xn|SP>, #<imm>, LSL #<shift>",
2377 .symbols = .{
2378 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2379 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
2380 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
2381 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 }, .multiple_of = 12 } },
2382 },
2383 .encode = .{ .subs, .Xd, .Xn, .{ .shifted_immediate = .{ .immediate = .imm, .lsl = .shift } } },
2384 },
2385 // C6.2.364 SUBS (shifted register)
2386 .{
2387 .pattern = "SUBS <Wd>, <Wn>, <Wm>",
2388 .symbols = .{
2389 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
2390 .Wn = .{ .reg = .{ .format = .{ .general = .word } } },
2391 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
2392 },
2393 .encode = .{ .subs, .Wd, .Wn, .{ .register = .Wm } },
2394 },
2395 .{
2396 .pattern = "SUBS <Wd>, <Wn>, <Wm>, <shift> #<amount>",
2397 .symbols = .{
2398 .Wd = .{ .reg = .{ .format = .{ .general = .word } } },
2399 .Wn = .{ .reg = .{ .format = .{ .general = .word } } },
2400 .Wm = .{ .reg = .{ .format = .{ .general = .word } } },
2401 .shift = .{ .shift = .{ .allow_ror = false } },
2402 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
2403 },
2404 .encode = .{ .subs, .Wd, .Wn, .{ .shifted_register_explicit = .{
2405 .register = .Wm,
2406 .shift = .shift,
2407 .amount = .amount,
2408 } } },
2409 },
2410 .{
2411 .pattern = "SUBS <Xd>, <Xn>, <Xm>",
2412 .symbols = .{
2413 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2414 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2415 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2416 },
2417 .encode = .{ .subs, .Xd, .Xn, .{ .register = .Xm } },
2418 },
2419 .{
2420 .pattern = "SUBS <Xd>, <Xn>, <Xm>, <shift> #<amount>",
2421 .symbols = .{
2422 .Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2423 .Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2424 .Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
2425 .shift = .{ .shift = .{ .allow_ror = false } },
2426 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
2427 },
2428 .encode = .{ .subs, .Xd, .Xn, .{ .shifted_register_explicit = .{
2429 .register = .Xm,
2430 .shift = .shift,
2431 .amount = .amount,
2432 } } },
2433 },
18082434 // C6.2.365 SVC
18092435 .{
18102436 .pattern = "SVC #<imm>",
......@@ -1933,6 +2559,13 @@
19332559 .symbols = .{},
19342560 .encode = .{.wfi},
19352561 },
2562 // C6.2.400 XAFLAG
2563 .{
2564 .requires = .{.altnzcv},
2565 .pattern = "XAFLAG",
2566 .symbols = .{},
2567 .encode = .{.xaflag},
2568 },
19362569 // C6.2.402 YIELD
19372570 .{
19382571 .pattern = "YIELD",