master
1/// B1.2 Registers in AArch64 Execution state
2pub const Register = struct {
3 alias: Alias,
4 format: Format,
5
6 pub const Format = union(enum) {
7 alias: Format.Alias,
8 general: GeneralSize,
9 scalar: ScalarSize,
10 vector: Arrangement,
11 element: struct { size: ScalarSize, index: u4 },
12 scalable,
13
14 pub const Alias = enum { general, other, vector, predicate };
15 };
16
17 pub const GeneralSize = enum(u1) {
18 word = 0b0,
19 doubleword = 0b1,
20
21 pub fn prefix(gs: GeneralSize) u8 {
22 return (comptime std.enums.EnumArray(GeneralSize, u8).init(.{
23 .word = 'w',
24 .doubleword = 'x',
25 })).get(gs);
26 }
27 };
28
29 pub const ScalarSize = enum(u3) {
30 byte = 0,
31 half = 1,
32 single = 2,
33 double = 3,
34 quad = 4,
35
36 pub fn n(ss: ScalarSize) ScalarSize {
37 return @enumFromInt(@intFromEnum(ss) - 1);
38 }
39
40 pub fn w(ss: ScalarSize) ScalarSize {
41 return @enumFromInt(@intFromEnum(ss) + 1);
42 }
43
44 pub fn prefix(ss: ScalarSize) u8 {
45 return (comptime std.enums.EnumArray(ScalarSize, u8).init(.{
46 .byte = 'b',
47 .half = 'h',
48 .single = 's',
49 .double = 'd',
50 .quad = 'q',
51 })).get(ss);
52 }
53 };
54
55 pub const Arrangement = enum(u3) {
56 @"2d" = @bitCast(Unwrapped{ .size = .quad, .elem_size = .double }),
57 @"4s" = @bitCast(Unwrapped{ .size = .quad, .elem_size = .single }),
58 @"8h" = @bitCast(Unwrapped{ .size = .quad, .elem_size = .half }),
59 @"16b" = @bitCast(Unwrapped{ .size = .quad, .elem_size = .byte }),
60
61 @"1d" = @bitCast(Unwrapped{ .size = .double, .elem_size = .double }),
62 @"2s" = @bitCast(Unwrapped{ .size = .double, .elem_size = .single }),
63 @"4h" = @bitCast(Unwrapped{ .size = .double, .elem_size = .half }),
64 @"8b" = @bitCast(Unwrapped{ .size = .double, .elem_size = .byte }),
65
66 pub const Unwrapped = packed struct {
67 size: Instruction.DataProcessingVector.Q,
68 elem_size: Instruction.DataProcessingVector.Size,
69 };
70 pub fn wrap(unwrapped: Unwrapped) Arrangement {
71 return @enumFromInt(@as(@typeInfo(Arrangement).@"enum".tag_type, @bitCast(unwrapped)));
72 }
73 pub fn unwrap(arrangement: Arrangement) Unwrapped {
74 return @bitCast(@intFromEnum(arrangement));
75 }
76
77 pub fn len(arrangement: Arrangement) u5 {
78 return switch (arrangement) {
79 .@"1d" => 1,
80 .@"2d", .@"2s" => 2,
81 .@"4s", .@"4h" => 4,
82 .@"8h", .@"8b" => 8,
83 .@"16b" => 16,
84 };
85 }
86
87 pub fn size(arrangement: Arrangement) Instruction.DataProcessingVector.Q {
88 return arrangement.unwrap().size;
89 }
90 pub fn elemSize(arrangement: Arrangement) Instruction.DataProcessingVector.Size {
91 return arrangement.unwrap().elem_size;
92 }
93 pub fn elemSz(arrangement: Arrangement) Instruction.DataProcessingVector.Sz {
94 return arrangement.elemSize().toSz();
95 }
96 };
97
98 pub const x0 = Alias.r0.x();
99 pub const x1 = Alias.r1.x();
100 pub const x2 = Alias.r2.x();
101 pub const x3 = Alias.r3.x();
102 pub const x4 = Alias.r4.x();
103 pub const x5 = Alias.r5.x();
104 pub const x6 = Alias.r6.x();
105 pub const x7 = Alias.r7.x();
106 pub const x8 = Alias.r8.x();
107 pub const x9 = Alias.r9.x();
108 pub const x10 = Alias.r10.x();
109 pub const x11 = Alias.r11.x();
110 pub const x12 = Alias.r12.x();
111 pub const x13 = Alias.r13.x();
112 pub const x14 = Alias.r14.x();
113 pub const x15 = Alias.r15.x();
114 pub const x16 = Alias.r16.x();
115 pub const x17 = Alias.r17.x();
116 pub const x18 = Alias.r18.x();
117 pub const x19 = Alias.r19.x();
118 pub const x20 = Alias.r20.x();
119 pub const x21 = Alias.r21.x();
120 pub const x22 = Alias.r22.x();
121 pub const x23 = Alias.r23.x();
122 pub const x24 = Alias.r24.x();
123 pub const x25 = Alias.r25.x();
124 pub const x26 = Alias.r26.x();
125 pub const x27 = Alias.r27.x();
126 pub const x28 = Alias.r28.x();
127 pub const x29 = Alias.r29.x();
128 pub const x30 = Alias.r30.x();
129 pub const xzr = Alias.zr.x();
130 pub const sp = Alias.sp.x();
131
132 pub const w0 = Alias.r0.w();
133 pub const w1 = Alias.r1.w();
134 pub const w2 = Alias.r2.w();
135 pub const w3 = Alias.r3.w();
136 pub const w4 = Alias.r4.w();
137 pub const w5 = Alias.r5.w();
138 pub const w6 = Alias.r6.w();
139 pub const w7 = Alias.r7.w();
140 pub const w8 = Alias.r8.w();
141 pub const w9 = Alias.r9.w();
142 pub const w10 = Alias.r10.w();
143 pub const w11 = Alias.r11.w();
144 pub const w12 = Alias.r12.w();
145 pub const w13 = Alias.r13.w();
146 pub const w14 = Alias.r14.w();
147 pub const w15 = Alias.r15.w();
148 pub const w16 = Alias.r16.w();
149 pub const w17 = Alias.r17.w();
150 pub const w18 = Alias.r18.w();
151 pub const w19 = Alias.r19.w();
152 pub const w20 = Alias.r20.w();
153 pub const w21 = Alias.r21.w();
154 pub const w22 = Alias.r22.w();
155 pub const w23 = Alias.r23.w();
156 pub const w24 = Alias.r24.w();
157 pub const w25 = Alias.r25.w();
158 pub const w26 = Alias.r26.w();
159 pub const w27 = Alias.r27.w();
160 pub const w28 = Alias.r28.w();
161 pub const w29 = Alias.r29.w();
162 pub const w30 = Alias.r30.w();
163 pub const wzr = Alias.zr.w();
164 pub const wsp = Alias.sp.w();
165
166 pub const ip = x16;
167 pub const ip0 = x16;
168 pub const ip1 = x17;
169 pub const fp = x29;
170 pub const lr = x30;
171 pub const pc = Alias.pc.alias(.other);
172
173 pub const q0 = Alias.v0.q();
174 pub const q1 = Alias.v1.q();
175 pub const q2 = Alias.v2.q();
176 pub const q3 = Alias.v3.q();
177 pub const q4 = Alias.v4.q();
178 pub const q5 = Alias.v5.q();
179 pub const q6 = Alias.v6.q();
180 pub const q7 = Alias.v7.q();
181 pub const q8 = Alias.v8.q();
182 pub const q9 = Alias.v9.q();
183 pub const q10 = Alias.v10.q();
184 pub const q11 = Alias.v11.q();
185 pub const q12 = Alias.v12.q();
186 pub const q13 = Alias.v13.q();
187 pub const q14 = Alias.v14.q();
188 pub const q15 = Alias.v15.q();
189 pub const q16 = Alias.v16.q();
190 pub const q17 = Alias.v17.q();
191 pub const q18 = Alias.v18.q();
192 pub const q19 = Alias.v19.q();
193 pub const q20 = Alias.v20.q();
194 pub const q21 = Alias.v21.q();
195 pub const q22 = Alias.v22.q();
196 pub const q23 = Alias.v23.q();
197 pub const q24 = Alias.v24.q();
198 pub const q25 = Alias.v25.q();
199 pub const q26 = Alias.v26.q();
200 pub const q27 = Alias.v27.q();
201 pub const q28 = Alias.v28.q();
202 pub const q29 = Alias.v29.q();
203 pub const q30 = Alias.v30.q();
204 pub const q31 = Alias.v31.q();
205
206 pub const d0 = Alias.v0.d();
207 pub const d1 = Alias.v1.d();
208 pub const d2 = Alias.v2.d();
209 pub const d3 = Alias.v3.d();
210 pub const d4 = Alias.v4.d();
211 pub const d5 = Alias.v5.d();
212 pub const d6 = Alias.v6.d();
213 pub const d7 = Alias.v7.d();
214 pub const d8 = Alias.v8.d();
215 pub const d9 = Alias.v9.d();
216 pub const d10 = Alias.v10.d();
217 pub const d11 = Alias.v11.d();
218 pub const d12 = Alias.v12.d();
219 pub const d13 = Alias.v13.d();
220 pub const d14 = Alias.v14.d();
221 pub const d15 = Alias.v15.d();
222 pub const d16 = Alias.v16.d();
223 pub const d17 = Alias.v17.d();
224 pub const d18 = Alias.v18.d();
225 pub const d19 = Alias.v19.d();
226 pub const d20 = Alias.v20.d();
227 pub const d21 = Alias.v21.d();
228 pub const d22 = Alias.v22.d();
229 pub const d23 = Alias.v23.d();
230 pub const d24 = Alias.v24.d();
231 pub const d25 = Alias.v25.d();
232 pub const d26 = Alias.v26.d();
233 pub const d27 = Alias.v27.d();
234 pub const d28 = Alias.v28.d();
235 pub const d29 = Alias.v29.d();
236 pub const d30 = Alias.v30.d();
237 pub const d31 = Alias.v31.d();
238
239 pub const s0 = Alias.v0.s();
240 pub const s1 = Alias.v1.s();
241 pub const s2 = Alias.v2.s();
242 pub const s3 = Alias.v3.s();
243 pub const s4 = Alias.v4.s();
244 pub const s5 = Alias.v5.s();
245 pub const s6 = Alias.v6.s();
246 pub const s7 = Alias.v7.s();
247 pub const s8 = Alias.v8.s();
248 pub const s9 = Alias.v9.s();
249 pub const s10 = Alias.v10.s();
250 pub const s11 = Alias.v11.s();
251 pub const s12 = Alias.v12.s();
252 pub const s13 = Alias.v13.s();
253 pub const s14 = Alias.v14.s();
254 pub const s15 = Alias.v15.s();
255 pub const s16 = Alias.v16.s();
256 pub const s17 = Alias.v17.s();
257 pub const s18 = Alias.v18.s();
258 pub const s19 = Alias.v19.s();
259 pub const s20 = Alias.v20.s();
260 pub const s21 = Alias.v21.s();
261 pub const s22 = Alias.v22.s();
262 pub const s23 = Alias.v23.s();
263 pub const s24 = Alias.v24.s();
264 pub const s25 = Alias.v25.s();
265 pub const s26 = Alias.v26.s();
266 pub const s27 = Alias.v27.s();
267 pub const s28 = Alias.v28.s();
268 pub const s29 = Alias.v29.s();
269 pub const s30 = Alias.v30.s();
270 pub const s31 = Alias.v31.s();
271
272 pub const h0 = Alias.v0.h();
273 pub const h1 = Alias.v1.h();
274 pub const h2 = Alias.v2.h();
275 pub const h3 = Alias.v3.h();
276 pub const h4 = Alias.v4.h();
277 pub const h5 = Alias.v5.h();
278 pub const h6 = Alias.v6.h();
279 pub const h7 = Alias.v7.h();
280 pub const h8 = Alias.v8.h();
281 pub const h9 = Alias.v9.h();
282 pub const h10 = Alias.v10.h();
283 pub const h11 = Alias.v11.h();
284 pub const h12 = Alias.v12.h();
285 pub const h13 = Alias.v13.h();
286 pub const h14 = Alias.v14.h();
287 pub const h15 = Alias.v15.h();
288 pub const h16 = Alias.v16.h();
289 pub const h17 = Alias.v17.h();
290 pub const h18 = Alias.v18.h();
291 pub const h19 = Alias.v19.h();
292 pub const h20 = Alias.v20.h();
293 pub const h21 = Alias.v21.h();
294 pub const h22 = Alias.v22.h();
295 pub const h23 = Alias.v23.h();
296 pub const h24 = Alias.v24.h();
297 pub const h25 = Alias.v25.h();
298 pub const h26 = Alias.v26.h();
299 pub const h27 = Alias.v27.h();
300 pub const h28 = Alias.v28.h();
301 pub const h29 = Alias.v29.h();
302 pub const h30 = Alias.v30.h();
303 pub const h31 = Alias.v31.h();
304
305 pub const b0 = Alias.v0.b();
306 pub const b1 = Alias.v1.b();
307 pub const b2 = Alias.v2.b();
308 pub const b3 = Alias.v3.b();
309 pub const b4 = Alias.v4.b();
310 pub const b5 = Alias.v5.b();
311 pub const b6 = Alias.v6.b();
312 pub const b7 = Alias.v7.b();
313 pub const b8 = Alias.v8.b();
314 pub const b9 = Alias.v9.b();
315 pub const b10 = Alias.v10.b();
316 pub const b11 = Alias.v11.b();
317 pub const b12 = Alias.v12.b();
318 pub const b13 = Alias.v13.b();
319 pub const b14 = Alias.v14.b();
320 pub const b15 = Alias.v15.b();
321 pub const b16 = Alias.v16.b();
322 pub const b17 = Alias.v17.b();
323 pub const b18 = Alias.v18.b();
324 pub const b19 = Alias.v19.b();
325 pub const b20 = Alias.v20.b();
326 pub const b21 = Alias.v21.b();
327 pub const b22 = Alias.v22.b();
328 pub const b23 = Alias.v23.b();
329 pub const b24 = Alias.v24.b();
330 pub const b25 = Alias.v25.b();
331 pub const b26 = Alias.v26.b();
332 pub const b27 = Alias.v27.b();
333 pub const b28 = Alias.v28.b();
334 pub const b29 = Alias.v29.b();
335 pub const b30 = Alias.v30.b();
336 pub const b31 = Alias.v31.b();
337
338 pub const fpcr = Alias.fpcr.alias(.other);
339 pub const fpsr = Alias.fpsr.alias(.other);
340
341 pub const z0 = Alias.v0.z();
342 pub const z1 = Alias.v1.z();
343 pub const z2 = Alias.v2.z();
344 pub const z3 = Alias.v3.z();
345 pub const z4 = Alias.v4.z();
346 pub const z5 = Alias.v5.z();
347 pub const z6 = Alias.v6.z();
348 pub const z7 = Alias.v7.z();
349 pub const z8 = Alias.v8.z();
350 pub const z9 = Alias.v9.z();
351 pub const z10 = Alias.v10.z();
352 pub const z11 = Alias.v11.z();
353 pub const z12 = Alias.v12.z();
354 pub const z13 = Alias.v13.z();
355 pub const z14 = Alias.v14.z();
356 pub const z15 = Alias.v15.z();
357 pub const z16 = Alias.v16.z();
358 pub const z17 = Alias.v17.z();
359 pub const z18 = Alias.v18.z();
360 pub const z19 = Alias.v19.z();
361 pub const z20 = Alias.v20.z();
362 pub const z21 = Alias.v21.z();
363 pub const z22 = Alias.v22.z();
364 pub const z23 = Alias.v23.z();
365 pub const z24 = Alias.v24.z();
366 pub const z25 = Alias.v25.z();
367 pub const z26 = Alias.v26.z();
368 pub const z27 = Alias.v27.z();
369 pub const z28 = Alias.v28.z();
370 pub const z29 = Alias.v29.z();
371 pub const z30 = Alias.v30.z();
372 pub const z31 = Alias.v31.z();
373
374 pub const p0 = Alias.p0.p();
375 pub const p1 = Alias.p1.p();
376 pub const p2 = Alias.p2.p();
377 pub const p3 = Alias.p3.p();
378 pub const p4 = Alias.p4.p();
379 pub const p5 = Alias.p5.p();
380 pub const p6 = Alias.p6.p();
381 pub const p7 = Alias.p7.p();
382 pub const p8 = Alias.p8.p();
383 pub const p9 = Alias.p9.p();
384 pub const p10 = Alias.p10.p();
385 pub const p11 = Alias.p11.p();
386 pub const p12 = Alias.p12.p();
387 pub const p13 = Alias.p13.p();
388 pub const p14 = Alias.p14.p();
389 pub const p15 = Alias.p15.p();
390
391 pub const ffr = Alias.ffr.alias(.other);
392
393 pub const Encoded = enum(u5) {
394 _,
395
396 pub fn decode(enc: Encoded, opts: struct { sp: bool = false, V: bool = false }) Alias {
397 return switch (opts.V) {
398 false => @enumFromInt(@intFromEnum(Alias.r0) + @intFromEnum(enc) +
399 @intFromBool(opts.sp and enc == comptime Alias.sp.encode(.{ .sp = true }))),
400 true => @enumFromInt(@intFromEnum(Alias.v0) + @intFromEnum(enc)),
401 };
402 }
403 };
404
405 /// One tag per set of aliasing registers.
406 pub const Alias = enum(u7) {
407 r0,
408 r1,
409 r2,
410 r3,
411 r4,
412 r5,
413 r6,
414 r7,
415 r8,
416 r9,
417 r10,
418 r11,
419 r12,
420 r13,
421 r14,
422 r15,
423 r16,
424 r17,
425 r18,
426 r19,
427 r20,
428 r21,
429 r22,
430 r23,
431 r24,
432 r25,
433 r26,
434 r27,
435 r28,
436 r29,
437 r30,
438 zr,
439 sp,
440
441 pc,
442
443 v0,
444 v1,
445 v2,
446 v3,
447 v4,
448 v5,
449 v6,
450 v7,
451 v8,
452 v9,
453 v10,
454 v11,
455 v12,
456 v13,
457 v14,
458 v15,
459 v16,
460 v17,
461 v18,
462 v19,
463 v20,
464 v21,
465 v22,
466 v23,
467 v24,
468 v25,
469 v26,
470 v27,
471 v28,
472 v29,
473 v30,
474 v31,
475
476 fpcr,
477 fpsr,
478
479 p0,
480 p1,
481 p2,
482 p3,
483 p4,
484 p5,
485 p6,
486 p7,
487 p8,
488 p9,
489 p10,
490 p11,
491 p12,
492 p13,
493 p14,
494 p15,
495
496 ffr,
497
498 pub const ip: Alias = .r16;
499 pub const ip0: Alias = .r16;
500 pub const ip1: Alias = .r17;
501 pub const fp: Alias = .r29;
502 pub const lr: Alias = .r30;
503
504 pub fn alias(ra: Alias, fa: Format.Alias) Register {
505 switch (fa) {
506 .general => assert(@intFromEnum(ra) >= @intFromEnum(Alias.r0) and @intFromEnum(ra) <= @intFromEnum(Alias.sp)),
507 .other => switch (ra) {
508 else => unreachable,
509 .pc, .fpcr, .fpsr, .ffr => {},
510 },
511 .vector => assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31)),
512 .predicate => assert(@intFromEnum(ra) >= @intFromEnum(Alias.p0) and @intFromEnum(ra) <= @intFromEnum(Alias.p15)),
513 }
514 return .{ .alias = ra, .format = .{ .alias = fa } };
515 }
516 pub fn general(ra: Alias, gs: GeneralSize) Register {
517 assert(@intFromEnum(ra) >= @intFromEnum(Alias.r0) and @intFromEnum(ra) <= @intFromEnum(Alias.sp));
518 return .{ .alias = ra, .format = .{ .general = gs } };
519 }
520 pub fn scalar(ra: Alias, ss: ScalarSize) Register {
521 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
522 return .{ .alias = ra, .format = .{ .scalar = ss } };
523 }
524 pub fn vector(ra: Alias, arrangement: Arrangement) Register {
525 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
526 return .{ .alias = ra, .format = .{ .vector = arrangement } };
527 }
528 pub fn element(ra: Alias, ss: ScalarSize, index: u4) Register {
529 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
530 return .{ .alias = ra, .format = .{ .element = .{ .size = ss, .index = index } } };
531 }
532 pub fn z(ra: Alias) Register {
533 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
534 return .{ .alias = ra, .format = .scalable };
535 }
536 pub fn p(ra: Alias) Register {
537 assert(@intFromEnum(ra) >= @intFromEnum(Alias.p0) and @intFromEnum(ra) <= @intFromEnum(Alias.p15));
538 return .{ .alias = ra, .format = .{ .scalar = .predicate } };
539 }
540
541 pub fn r(ra: Alias) Register {
542 return ra.alias(.general);
543 }
544 pub fn x(ra: Alias) Register {
545 return ra.general(.doubleword);
546 }
547 pub fn w(ra: Alias) Register {
548 return ra.general(.word);
549 }
550 pub fn v(ra: Alias) Register {
551 return ra.alias(.vector);
552 }
553 pub fn q(ra: Alias) Register {
554 return ra.scalar(.quad);
555 }
556 pub fn d(ra: Alias) Register {
557 return ra.scalar(.double);
558 }
559 pub fn s(ra: Alias) Register {
560 return ra.scalar(.single);
561 }
562 pub fn h(ra: Alias) Register {
563 return ra.scalar(.half);
564 }
565 pub fn b(ra: Alias) Register {
566 return ra.scalar(.byte);
567 }
568 pub fn @"2d"(ra: Alias) Register {
569 return ra.vector(.@"2d");
570 }
571 pub fn @"4s"(ra: Alias) Register {
572 return ra.vector(.@"4s");
573 }
574 pub fn @"8h"(ra: Alias) Register {
575 return ra.vector(.@"8h");
576 }
577 pub fn @"16b"(ra: Alias) Register {
578 return ra.vector(.@"16b");
579 }
580 pub fn @"1d"(ra: Alias) Register {
581 return ra.vector(.@"1d");
582 }
583 pub fn @"2s"(ra: Alias) Register {
584 return ra.vector(.@"2s");
585 }
586 pub fn @"4h"(ra: Alias) Register {
587 return ra.vector(.@"4h");
588 }
589 pub fn @"8b"(ra: Alias) Register {
590 return ra.vector(.@"8b");
591 }
592 pub fn @"d[]"(ra: Alias, index: u1) Register {
593 return ra.element(.double, index);
594 }
595 pub fn @"s[]"(ra: Alias, index: u2) Register {
596 return ra.element(.single, index);
597 }
598 pub fn @"h[]"(ra: Alias, index: u3) Register {
599 return ra.element(.half, index);
600 }
601 pub fn @"b[]"(ra: Alias, index: u4) Register {
602 return ra.element(.byte, index);
603 }
604
605 pub fn isVector(ra: Alias) bool {
606 return switch (ra) {
607 .r0,
608 .r1,
609 .r2,
610 .r3,
611 .r4,
612 .r5,
613 .r6,
614 .r7,
615 .r8,
616 .r9,
617 .r10,
618 .r11,
619 .r12,
620 .r13,
621 .r14,
622 .r15,
623 .r16,
624 .r17,
625 .r18,
626 .r19,
627 .r20,
628 .r21,
629 .r22,
630 .r23,
631 .r24,
632 .r25,
633 .r26,
634 .r27,
635 .r28,
636 .r29,
637 .r30,
638 .zr,
639 .sp,
640
641 .pc,
642
643 .fpcr,
644 .fpsr,
645
646 .ffr,
647 => false,
648
649 .v0,
650 .v1,
651 .v2,
652 .v3,
653 .v4,
654 .v5,
655 .v6,
656 .v7,
657 .v8,
658 .v9,
659 .v10,
660 .v11,
661 .v12,
662 .v13,
663 .v14,
664 .v15,
665 .v16,
666 .v17,
667 .v18,
668 .v19,
669 .v20,
670 .v21,
671 .v22,
672 .v23,
673 .v24,
674 .v25,
675 .v26,
676 .v27,
677 .v28,
678 .v29,
679 .v30,
680 .v31,
681
682 .p0,
683 .p1,
684 .p2,
685 .p3,
686 .p4,
687 .p5,
688 .p6,
689 .p7,
690 .p8,
691 .p9,
692 .p10,
693 .p11,
694 .p12,
695 .p13,
696 .p14,
697 .p15,
698 => true,
699 };
700 }
701
702 pub fn encode(ra: Alias, comptime opts: struct { sp: bool = false, V: bool = false }) Encoded {
703 return @enumFromInt(@as(u5, switch (ra) {
704 .r0 => if (opts.V) unreachable else 0,
705 .r1 => if (opts.V) unreachable else 1,
706 .r2 => if (opts.V) unreachable else 2,
707 .r3 => if (opts.V) unreachable else 3,
708 .r4 => if (opts.V) unreachable else 4,
709 .r5 => if (opts.V) unreachable else 5,
710 .r6 => if (opts.V) unreachable else 6,
711 .r7 => if (opts.V) unreachable else 7,
712 .r8 => if (opts.V) unreachable else 8,
713 .r9 => if (opts.V) unreachable else 9,
714 .r10 => if (opts.V) unreachable else 10,
715 .r11 => if (opts.V) unreachable else 11,
716 .r12 => if (opts.V) unreachable else 12,
717 .r13 => if (opts.V) unreachable else 13,
718 .r14 => if (opts.V) unreachable else 14,
719 .r15 => if (opts.V) unreachable else 15,
720 .r16 => if (opts.V) unreachable else 16,
721 .r17 => if (opts.V) unreachable else 17,
722 .r18 => if (opts.V) unreachable else 18,
723 .r19 => if (opts.V) unreachable else 19,
724 .r20 => if (opts.V) unreachable else 20,
725 .r21 => if (opts.V) unreachable else 21,
726 .r22 => if (opts.V) unreachable else 22,
727 .r23 => if (opts.V) unreachable else 23,
728 .r24 => if (opts.V) unreachable else 24,
729 .r25 => if (opts.V) unreachable else 25,
730 .r26 => if (opts.V) unreachable else 26,
731 .r27 => if (opts.V) unreachable else 27,
732 .r28 => if (opts.V) unreachable else 28,
733 .r29 => if (opts.V) unreachable else 29,
734 .r30 => if (opts.V) unreachable else 30,
735 .zr => if (opts.sp or opts.V) unreachable else 31,
736 .sp => if (opts.sp and !opts.V) 31 else unreachable,
737 .pc => unreachable,
738 .v0 => if (opts.V) 0 else unreachable,
739 .v1 => if (opts.V) 1 else unreachable,
740 .v2 => if (opts.V) 2 else unreachable,
741 .v3 => if (opts.V) 3 else unreachable,
742 .v4 => if (opts.V) 4 else unreachable,
743 .v5 => if (opts.V) 5 else unreachable,
744 .v6 => if (opts.V) 6 else unreachable,
745 .v7 => if (opts.V) 7 else unreachable,
746 .v8 => if (opts.V) 8 else unreachable,
747 .v9 => if (opts.V) 9 else unreachable,
748 .v10 => if (opts.V) 10 else unreachable,
749 .v11 => if (opts.V) 11 else unreachable,
750 .v12 => if (opts.V) 12 else unreachable,
751 .v13 => if (opts.V) 13 else unreachable,
752 .v14 => if (opts.V) 14 else unreachable,
753 .v15 => if (opts.V) 15 else unreachable,
754 .v16 => if (opts.V) 16 else unreachable,
755 .v17 => if (opts.V) 17 else unreachable,
756 .v18 => if (opts.V) 18 else unreachable,
757 .v19 => if (opts.V) 19 else unreachable,
758 .v20 => if (opts.V) 20 else unreachable,
759 .v21 => if (opts.V) 21 else unreachable,
760 .v22 => if (opts.V) 22 else unreachable,
761 .v23 => if (opts.V) 23 else unreachable,
762 .v24 => if (opts.V) 24 else unreachable,
763 .v25 => if (opts.V) 25 else unreachable,
764 .v26 => if (opts.V) 26 else unreachable,
765 .v27 => if (opts.V) 27 else unreachable,
766 .v28 => if (opts.V) 28 else unreachable,
767 .v29 => if (opts.V) 29 else unreachable,
768 .v30 => if (opts.V) 30 else unreachable,
769 .v31 => if (opts.V) 31 else unreachable,
770 .fpcr, .fpsr => unreachable,
771 .p0, .p1, .p2, .p3, .p4, .p5, .p6, .p7, .p8, .p9, .p10, .p11, .p12, .p13, .p14, .p15 => unreachable,
772 .ffr => unreachable,
773 }));
774 }
775 };
776
777 pub fn isVector(reg: Register) bool {
778 return reg.alias.isVector();
779 }
780
781 pub fn size(reg: Register) ?u5 {
782 return format: switch (reg.format) {
783 .alias => unreachable,
784 .general => |sf| switch (sf) {
785 .word => 4,
786 .doubleword => 8,
787 },
788 .scalar => |elem_size| switch (elem_size) {
789 .byte => 1,
790 .half => 2,
791 .single => 4,
792 .double => 8,
793 .quad => 16,
794 },
795 .vector => |arrangement| switch (arrangement) {
796 .@"2d", .@"4s", .@"8h", .@"16b" => 16,
797 .@"1d", .@"2s", .@"4h", .@"8b" => 8,
798 },
799 .element => |element| continue :format .{ .scalar = element.size },
800 .scalable => null,
801 };
802 }
803
804 pub fn parse(reg: []const u8) ?Register {
805 return if (reg.len == 0) null else switch (std.ascii.toLower(reg[0])) {
806 else => null,
807 'r' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| switch (n) {
808 0...30 => .{
809 .alias = @enumFromInt(@intFromEnum(Alias.r0) + n),
810 .format = .{ .alias = .general },
811 },
812 31 => null,
813 } else |_| null,
814 'x' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| switch (n) {
815 0...30 => .{
816 .alias = @enumFromInt(@intFromEnum(Alias.r0) + n),
817 .format = .{ .general = .doubleword },
818 },
819 31 => null,
820 } else |_| if (toLowerEqlAssertLower(reg, "xzr")) .xzr else null,
821 'w' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| switch (n) {
822 0...30 => .{
823 .alias = @enumFromInt(@intFromEnum(Alias.r0) + n),
824 .format = .{ .general = .word },
825 },
826 31 => null,
827 } else |_| if (toLowerEqlAssertLower(reg, "wzr"))
828 .wzr
829 else if (toLowerEqlAssertLower(reg, "wsp"))
830 .wsp
831 else
832 null,
833 'i' => return if (toLowerEqlAssertLower(reg, "ip") or toLowerEqlAssertLower(reg, "ip0"))
834 .ip0
835 else if (toLowerEqlAssertLower(reg, "ip1"))
836 .ip1
837 else
838 null,
839 'f' => return if (toLowerEqlAssertLower(reg, "fp")) .fp else null,
840 'p' => return if (toLowerEqlAssertLower(reg, "pc")) .pc else null,
841 'v' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
842 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
843 .format = .{ .alias = .vector },
844 } else |_| null,
845 'q' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
846 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
847 .format = .{ .scalar = .quad },
848 } else |_| null,
849 'd' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
850 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
851 .format = .{ .scalar = .double },
852 } else |_| null,
853 's' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
854 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
855 .format = .{ .scalar = .single },
856 } else |_| if (toLowerEqlAssertLower(reg, "sp")) .sp else null,
857 'h' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
858 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
859 .format = .{ .scalar = .half },
860 } else |_| null,
861 'b' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
862 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
863 .format = .{ .scalar = .byte },
864 } else |_| null,
865 };
866 }
867
868 pub fn fmt(reg: Register) aarch64.Disassemble.RegisterFormatter {
869 return reg.fmtCase(.lower);
870 }
871 pub fn fmtCase(reg: Register, case: aarch64.Disassemble.Case) aarch64.Disassemble.RegisterFormatter {
872 return .{ .reg = reg, .case = case };
873 }
874
875 pub const System = packed struct(u16) {
876 op2: u3,
877 CRm: u4,
878 CRn: u4,
879 op1: u3,
880 op0: u2,
881
882 // D19.2 General system control registers
883 /// D19.2.1 ACCDATA_EL1, Accelerator Data
884 pub const accdata_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b101 };
885 /// D19.2.2 ACTLR_EL1, Auxiliary Control Register (EL1)
886 pub const actlr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b001 };
887 /// D19.2.3 ACTLR_EL2, Auxiliary Control Register (EL2)
888 pub const actlr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b001 };
889 /// D19.2.4 ACTLR_EL3, Auxiliary Control Register (EL3)
890 pub const actlr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b001 };
891 /// D19.2.5 AFSR0_EL1, Auxiliary Fault Status Register 0 (EL1)
892 pub const afsr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b000 };
893 /// D19.2.5 AFSR0_EL12, Auxiliary Fault Status Register 0 (EL12)
894 pub const afsr0_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b000 };
895 /// D19.2.6 AFSR0_EL2, Auxiliary Fault Status Register 0 (EL2)
896 pub const afsr0_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b000 };
897 /// D19.2.7 AFSR0_EL3, Auxiliary Fault Status Register 0 (EL3)
898 pub const afsr0_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b000 };
899 /// D19.2.8 AFSR1_EL1, Auxiliary Fault Status Register 1 (EL1)
900 pub const afsr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b001 };
901 /// D19.2.8 AFSR1_EL12, Auxiliary Fault Status Register 1 (EL12)
902 pub const afsr1_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b001 };
903 /// D19.2.9 AFSR1_EL2, Auxiliary Fault Status Register 1 (EL2)
904 pub const afsr1_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b001 };
905 /// D19.2.10 AFSR1_EL3, Auxiliary Fault Status Register 1 (EL3)
906 pub const afsr1_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b001 };
907 /// D19.2.11 AIDR_EL1, Auxiliary ID Register
908 pub const aidr_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b111 };
909 /// D19.2.12 AMAIR_EL1, Auxiliary Memory Attribute Indirection Register (EL1)
910 pub const amair_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0011, .op2 = 0b000 };
911 /// D19.2.12 AMAIR_EL12, Auxiliary Memory Attribute Indirection Register (EL12)
912 pub const amair_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1010, .CRm = 0b0011, .op2 = 0b000 };
913 /// D19.2.13 AMAIR_EL2, Auxiliary Memory Attribute Indirection Register (EL2)
914 pub const amair_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1010, .CRm = 0b0011, .op2 = 0b000 };
915 /// D19.2.14 AMAIR_EL3, Auxiliary Memory Attribute Indirection Register (EL3)
916 pub const amair_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1010, .CRm = 0b0011, .op2 = 0b000 };
917 /// D19.2.15 APDAKeyHi_EL1, Pointer Authentication Key A for Data (bits[127:64])
918 pub const apdakeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b001 };
919 /// D19.2.16 APDAKeyLo_EL1, Pointer Authentication Key A for Data (bits[63:0])
920 pub const apdakeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b000 };
921 /// D19.2.17 APDBKeyHi_EL1, Pointer Authentication Key B for Data (bits[127:64])
922 pub const apdbkeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b011 };
923 /// D19.2.18 APDAKeyHi_EL1, Pointer Authentication Key B for Data (bits[63:0])
924 pub const apdbkeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b010 };
925 /// D19.2.19 APGAKeyHi_EL1, Pointer Authentication Key A for Code (bits[127:64])
926 pub const apgakeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0011, .op2 = 0b001 };
927 /// D19.2.20 APGAKeyLo_EL1, Pointer Authentication Key A for Code (bits[63:0])
928 pub const apgakeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0011, .op2 = 0b000 };
929 /// D19.2.21 APIAKeyHi_EL1, Pointer Authentication Key A for Instruction (bits[127:64])
930 pub const apiakeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b001 };
931 /// D19.2.22 APIAKeyLo_EL1, Pointer Authentication Key A for Instruction (bits[63:0])
932 pub const apiakeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b000 };
933 /// D19.2.23 APIBKeyHi_EL1, Pointer Authentication Key B for Instruction (bits[127:64])
934 pub const apibkeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b011 };
935 /// D19.2.24 APIBKeyLo_EL1, Pointer Authentication Key B for Instruction (bits[63:0])
936 pub const apibkeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b010 };
937 /// D19.2.25 CCSIDR2_EL1, Current Cache Size ID Register 2
938 pub const ccsidr2_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b010 };
939 /// D19.2.26 CCSIDR_EL1, Current Cache Size ID Register
940 pub const ccsidr_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b000 };
941 /// D19.2.27 CLIDR_EL1, Cache Level ID Register
942 pub const clidr_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b001 };
943 /// D19.2.28 CONTEXTIDR_EL1, Context ID Register (EL1)
944 pub const contextidr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b001 };
945 /// D19.2.28 CONTEXTIDR_EL12, Context ID Register (EL12)
946 pub const contextidr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b001 };
947 /// D19.2.29 CONTEXTIDR_EL2, Context ID Register (EL2)
948 pub const contextidr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b001 };
949 /// D19.2.30 CPACR_EL1, Architectural Feature Access Control Register
950 pub const cpacr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b010 };
951 /// D19.2.30 CPACR_EL12, Architectural Feature Access Control Register
952 pub const cpacr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b010 };
953 /// D19.2.31 CPACR_EL2, Architectural Feature Trap Register (EL2)
954 pub const cptr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b010 };
955 /// D19.2.32 CPACR_EL3, Architectural Feature Trap Register (EL3)
956 pub const cptr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b010 };
957 /// D19.2.33 CSSELR_EL1, Cache Size Selection Register
958 pub const csselr_el1: System = .{ .op0 = 0b11, .op1 = 0b010, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b000 };
959 /// D19.2.34 CTR_EL0, Cache Type Register
960 pub const ctr_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b001 };
961 /// D19.2.35 DACR32_EL2, Domain Access Control Register
962 pub const dacr32_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0011, .CRm = 0b0000, .op2 = 0b000 };
963 /// D19.2.36 DCZID_EL0, Data Cache Zero ID Register
964 pub const dczid_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b111 };
965 /// D19.2.37 ESR_EL1, Exception Syndrome Register (EL1)
966 pub const esr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0010, .op2 = 0b000 };
967 /// D19.2.37 ESR_EL12, Exception Syndrome Register (EL12)
968 pub const esr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0101, .CRm = 0b0010, .op2 = 0b000 };
969 /// D19.2.38 ESR_EL2, Exception Syndrome Register (EL2)
970 pub const esr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0010, .op2 = 0b000 };
971 /// D19.2.39 ESR_EL3, Exception Syndrome Register (EL3)
972 pub const esr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0101, .CRm = 0b0010, .op2 = 0b000 };
973 /// D19.2.40 FAR_EL1, Fault Address Register (EL1)
974 pub const far_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b000 };
975 /// D19.2.40 FAR_EL12, Fault Address Register (EL12)
976 pub const far_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b000 };
977 /// D19.2.41 FAR_EL2, Fault Address Register (EL2)
978 pub const far_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b000 };
979 /// D19.2.42 FAR_EL3, Fault Address Register (EL3)
980 pub const far_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b000 };
981 /// D19.2.43 FPEXC32_EL2, Floating-Point Exception Control Register
982 pub const fpexc32_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0011, .op2 = 0b000 };
983 /// D19.2.44 GCR_EL1, Tag Control Register
984 pub const gcr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b110 };
985 /// D19.2.45 GMID_EL1, Tag Control Register
986 pub const gmid_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b100 };
987 /// D19.2.46 HACR_EL2, Hypervisor Auxiliary Control Register
988 pub const hacr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b111 };
989 /// D19.2.47 HAFGRTR_EL2, Hypervisor Activity Monitors Fine-Grained Read Trap Register
990 pub const hafgrtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0011, .CRm = 0b0001, .op2 = 0b110 };
991 /// D19.2.48 HCR_EL2, Hypervisor Configuration Register
992 pub const hcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b000 };
993 /// D19.2.49 HCRX_EL2, Extended Hypervisor Configuration Register
994 pub const hcrx_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b010 };
995 /// D19.2.50 HDFGRTR_EL2, Hypervisor Debug Fine-Grained Read Trap Register
996 pub const hdfgrtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0011, .CRm = 0b0001, .op2 = 0b100 };
997 /// D19.2.51 HDFGWTR_EL2, Hypervisor Debug Fine-Grained Write Trap Register
998 pub const hdfgwtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0011, .CRm = 0b0001, .op2 = 0b101 };
999 /// D19.2.52 HFGITR_EL2, Hypervisor Fine-Grained Instruction Trap Register
1000 pub const hfgitr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b110 };
1001 /// D19.2.53 HFGRTR_EL2, Hypervisor Fine-Grained Read Trap Register
1002 pub const hfgrtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b100 };
1003 /// D19.2.54 HFGWTR_EL2, Hypervisor Fine-Grained Write Trap Register
1004 pub const hfgwtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b101 };
1005 /// D19.2.55 HPFAR_EL2, Hypervisor IPA Fault Address Register
1006 pub const hpfar_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b100 };
1007 /// D19.2.56 HSTR_EL2, Hypervisor System Trap Register
1008 pub const hstr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b011 };
1009 /// D19.2.57 ID_AA64AFR0_EL1, AArch64 Auxiliary Feature Register 0
1010 pub const id_aa64afr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0101, .op2 = 0b100 };
1011 /// D19.2.58 ID_AA64AFR1_EL1, AArch64 Auxiliary Feature Register 1
1012 pub const id_aa64afr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0101, .op2 = 0b101 };
1013 /// D19.2.59 ID_AA64DFR0_EL1, AArch64 Debug Feature Register 0
1014 pub const id_aa64dfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0101, .op2 = 0b000 };
1015 /// D19.2.60 ID_AA64DFR1_EL1, AArch64 Debug Feature Register 1
1016 pub const id_aa64dfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0101, .op2 = 0b001 };
1017 /// D19.2.61 ID_AA64ISAR0_EL1, AArch64 Instruction Set Attribute Register 0
1018 pub const id_aa64isar0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0110, .op2 = 0b000 };
1019 /// D19.2.62 ID_AA64ISAR1_EL1, AArch64 Instruction Set Attribute Register 1
1020 pub const id_aa64isar1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0110, .op2 = 0b001 };
1021 /// D19.2.63 ID_AA64ISAR2_EL1, AArch64 Instruction Set Attribute Register 2
1022 pub const id_aa64isar2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0110, .op2 = 0b010 };
1023 /// D19.2.64 ID_AA64MMFR0_EL1, AArch64 Memory Model Feature Register 0
1024 pub const id_aa64mmfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b000 };
1025 /// D19.2.65 ID_AA64MMFR1_EL1, AArch64 Memory Model Feature Register 1
1026 pub const id_aa64mmfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b001 };
1027 /// D19.2.66 ID_AA64MMFR2_EL1, AArch64 Memory Model Feature Register 2
1028 pub const id_aa64mmfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b010 };
1029 /// D19.2.67 ID_AA64MMFR3_EL1, AArch64 Memory Model Feature Register 3
1030 pub const id_aa64mmfr3_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b011 };
1031 /// D19.2.68 ID_AA64MMFR4_EL1, AArch64 Memory Model Feature Register 4
1032 pub const id_aa64mmfr4_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b100 };
1033 /// D19.2.69 ID_AA64PFR0_EL1, AArch64 Processor Feature Register 0
1034 pub const id_aa64pfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b000 };
1035 /// D19.2.70 ID_AA64PFR1_EL1, AArch64 Processor Feature Register 1
1036 pub const id_aa64pfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b001 };
1037 /// D19.2.71 ID_AA64PFR2_EL1, AArch64 Processor Feature Register 2
1038 pub const id_aa64pfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b010 };
1039 /// D19.2.72 ID_AA64SMFR0_EL1, SME Feature ID Register 0
1040 pub const id_aa64smfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b101 };
1041 /// D19.2.73 ID_AA64ZFR0_EL1, SVE Feature ID Register 0
1042 pub const id_aa64zfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b100 };
1043 /// D19.2.74 ID_AFR0_EL1, AArch32 Auxiliary Feature Register 0
1044 pub const id_afr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b011 };
1045 /// D19.2.75 ID_DFR0_EL1, AArch32 Debug Feature Register 0
1046 pub const id_dfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b010 };
1047 /// D19.2.76 ID_DFR1_EL1, AArch32 Debug Feature Register 1
1048 pub const id_dfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b101 };
1049 /// D19.2.77 ID_ISAR0_EL1, AArch32 Instruction Set Attribute Register 0
1050 pub const id_isar0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b000 };
1051 /// D19.2.78 ID_ISAR1_EL1, AArch32 Instruction Set Attribute Register 1
1052 pub const id_isar1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b001 };
1053 /// D19.2.79 ID_ISAR2_EL1, AArch32 Instruction Set Attribute Register 2
1054 pub const id_isar2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b010 };
1055 /// D19.2.80 ID_ISAR3_EL1, AArch32 Instruction Set Attribute Register 3
1056 pub const id_isar3_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b011 };
1057 /// D19.2.81 ID_ISAR4_EL1, AArch32 Instruction Set Attribute Register 4
1058 pub const id_isar4_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b100 };
1059 /// D19.2.82 ID_ISAR5_EL1, AArch32 Instruction Set Attribute Register 5
1060 pub const id_isar5_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b101 };
1061 /// D19.2.83 ID_ISAR6_EL1, AArch32 Instruction Set Attribute Register 6
1062 pub const id_isar6_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b111 };
1063 /// D19.2.84 ID_MMFR0_EL1, AArch32 Memory Model Feature Register 0
1064 pub const id_mmfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b100 };
1065 /// D19.2.85 ID_MMFR1_EL1, AArch32 Memory Model Feature Register 1
1066 pub const id_mmfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b101 };
1067 /// D19.2.86 ID_MMFR2_EL1, AArch32 Memory Model Feature Register 2
1068 pub const id_mmfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b110 };
1069 /// D19.2.87 ID_MMFR3_EL1, AArch32 Memory Model Feature Register 3
1070 pub const id_mmfr3_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b111 };
1071 /// D19.2.88 ID_MMFR4_EL1, AArch32 Memory Model Feature Register 4
1072 pub const id_mmfr4_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b110 };
1073 /// D19.2.89 ID_MMFR5_EL1, AArch32 Memory Model Feature Register 5
1074 pub const id_mmfr5_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b110 };
1075 /// D19.2.90 ID_PFR0_EL1, AArch32 Processor Feature Register 0
1076 pub const id_pfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b000 };
1077 /// D19.2.91 ID_PFR1_EL1, AArch32 Processor Feature Register 1
1078 pub const id_pfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b001 };
1079 /// D19.2.92 ID_PFR2_EL1, AArch32 Processor Feature Register 2
1080 pub const id_pfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b100 };
1081 /// D19.2.93 IFSR32_EL2, Instruction Fault Status Register (EL2)
1082 pub const ifsr32_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0000, .op2 = 0b001 };
1083 /// D19.2.94 ISR_EL1, Interrupt Status Register
1084 pub const isr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1100, .CRm = 0b0001, .op2 = 0b000 };
1085 /// D19.2.95 LORC_EL1, LORegion Control (EL1)
1086 pub const lorc_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b011 };
1087 /// D19.2.96 LOREA_EL1, LORegion End Address (EL1)
1088 pub const lorea_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b001 };
1089 /// D19.2.97 SORID_EL1, LORegionID (EL1)
1090 pub const lorid_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b111 };
1091 /// D19.2.98 LORN_EL1, LORegion Number (EL1)
1092 pub const lorn_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b010 };
1093 /// D19.2.99 LORSA_EL1, LORegion Start Address (EL1)
1094 pub const lorsa_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b000 };
1095 /// D19.2.100 MAIR_EL1, Memory Attribute Indirection Register (EL1)
1096 pub const mair_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0010, .op2 = 0b000 };
1097 /// D19.2.100 MAIR_EL12, Memory Attribute Indirection Register (EL12)
1098 pub const mair_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1010, .CRm = 0b0010, .op2 = 0b000 };
1099 /// D19.2.101 MAIR_EL2, Memory Attribute Indirection Register (EL2)
1100 pub const mair_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1010, .CRm = 0b0010, .op2 = 0b000 };
1101 /// D19.2.102 MAIR_EL3, Memory Attribute Indirection Register (EL3)
1102 pub const mair_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1010, .CRm = 0b0010, .op2 = 0b000 };
1103 /// D19.2.103 MIDR_EL1, Main ID Register
1104 pub const midr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b000 };
1105 /// D19.2.104 MPIDR_EL1, Multiprocessor Affinity Register
1106 pub const mpidr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b101 };
1107 /// D19.2.105 MVFR0_EL1, AArch32 Media and VFP Feature Register 0
1108 pub const mvfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b000 };
1109 /// D19.2.106 MVFR1_EL1, AArch32 Media and VFP Feature Register 1
1110 pub const mvfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b001 };
1111 /// D19.2.107 MVFR2_EL1, AArch32 Media and VFP Feature Register 2
1112 pub const mvfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b010 };
1113 /// D19.2.108 PAR_EL1, Physical Address Register
1114 pub const par_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0111, .CRm = 0b0100, .op2 = 0b000 };
1115 /// D19.2.109 REVIDR_EL1, Revision ID Register
1116 pub const revidr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b110 };
1117 /// D19.2.110 RGSR_EL1, Random Allocation Tag Seed Register
1118 pub const rgsr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b101 };
1119 /// D19.2.111 RMR_EL1, Reset Management Register (EL1)
1120 pub const rmr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b010 };
1121 /// D19.2.112 RMR_EL2, Reset Management Register (EL2)
1122 pub const rmr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b010 };
1123 /// D19.2.113 RMR_EL3, Reset Management Register (EL3)
1124 pub const rmr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b010 };
1125 /// D19.2.114 RNDR, Random Number
1126 pub const rndr: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b0010, .CRm = 0b0100, .op2 = 0b000 };
1127 /// D19.2.115 RNDRRS, Reseeded Random Number
1128 pub const rndrrs: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b0010, .CRm = 0b0100, .op2 = 0b001 };
1129 /// D19.2.116 RVBAR_EL1, Reset Vector Base Address Register (if EL2 and EL3 not implemented)
1130 pub const rvbar_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b001 };
1131 /// D19.2.117 RVBAR_EL2, Reset Vector Base Address Register (if EL3 not implemented)
1132 pub const rvbar_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b001 };
1133 /// D19.2.118 RVBAR_EL3, Reset Vector Base Address Register (if EL3 implemented)
1134 pub const rvbar_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b001 };
1135 /// D19.2.120 SCR_EL3, Secure Configuration Register
1136 pub const scr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b000 };
1137 /// D19.2.121 SCTLR2_EL1, System Control Register (EL1)
1138 pub const sctlr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b011 };
1139 /// D19.2.121 SCTLR2_EL12, System Control Register (EL12)
1140 pub const sctlr2_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b011 };
1141 /// D19.2.122 SCTLR2_EL2, System Control Register (EL2)
1142 pub const sctlr2_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b011 };
1143 /// D19.2.123 SCTLR2_EL3, System Control Register (EL3)
1144 pub const sctlr2_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b011 };
1145 /// D19.2.124 SCTLR_EL1, System Control Register (EL1)
1146 pub const sctlr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b000 };
1147 /// D19.2.124 SCTLR_EL12, System Control Register (EL12)
1148 pub const sctlr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b000 };
1149 /// D19.2.125 SCTLR_EL2, System Control Register (EL2)
1150 pub const sctlr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b000 };
1151 /// D19.2.126 SCTLR_EL3, System Control Register (EL3)
1152 pub const sctlr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b000 };
1153 /// D19.2.127 SCXTNUM_EL0, EL0 Read/Write Software Context Number
1154 pub const scxtnum_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
1155 /// D19.2.128 SCXTNUM_EL1, EL1 Read/Write Software Context Number
1156 pub const scxtnum_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
1157 /// D19.2.128 SCXTNUM_EL12, EL12 Read/Write Software Context Number
1158 pub const scxtnum_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
1159 /// D19.2.129 SCXTNUM_EL2, EL2 Read/Write Software Context Number
1160 pub const scxtnum_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
1161 /// D19.2.130 SCXTNUM_EL3, EL3 Read/Write Software Context Number
1162 pub const scxtnum_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
1163 /// D19.2.131 SMCR_EL1, SME Control Register (EL1)
1164 pub const smcr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b110 };
1165 /// D19.2.131 SMCR_EL12, SME Control Register (EL12)
1166 pub const smcr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b110 };
1167 /// D19.2.132 SMCR_EL2, SME Control Register (EL2)
1168 pub const smcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b110 };
1169 /// D19.2.133 SMCR_EL3, SME Control Register (EL3)
1170 pub const smcr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b110 };
1171 /// D19.2.134 SMIDR_EL1, Streaming Mode Identification Register
1172 pub const smidr_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b110 };
1173 /// D19.2.135 SMPRIMAP_EL2, Streaming Mode Priority Mapping Register
1174 pub const smprimap_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b101 };
1175 /// D19.2.136 SMPRI_EL1, Streaming Mode Priority Register
1176 pub const smpri_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b100 };
1177 /// D19.2.137 TCR2_EL1, Extended Translation Control Register (EL1)
1178 pub const tcr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b011 };
1179 /// D19.2.137 TCR2_EL12, Extended Translation Control Register (EL12)
1180 pub const tcr2_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b011 };
1181 /// D19.2.138 TCR2_EL2, Extended Translation Control Register (EL2)
1182 pub const tcr2_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b011 };
1183 /// D19.2.139 TCR_EL1, Translation Control Register (EL1)
1184 pub const tcr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b010 };
1185 /// D19.2.139 TCR_EL12, Translation Control Register (EL12)
1186 pub const tcr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b010 };
1187 /// D19.2.140 TCR_EL2, Translation Control Register (EL2)
1188 pub const tcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b010 };
1189 /// D19.2.141 TCR_EL3, Translation Control Register (EL3)
1190 pub const tcr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b010 };
1191 /// D19.2.142 TFSRE0_EL1, Tag Fault Status Register (EL0)
1192 pub const tfsre0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b001 };
1193 /// D19.2.143 TFSR_EL1, Tag Fault Status Register (EL1)
1194 pub const tfsr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b000 };
1195 /// D19.2.143 TFSR_EL12, Tag Fault Status Register (EL12)
1196 pub const tfsr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b000 };
1197 /// D19.2.144 TFSR_EL2, Tag Fault Status Register (EL2)
1198 pub const tfsr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b000 };
1199 /// D19.2.145 TFSR_EL3, Tag Fault Status Register (EL3)
1200 pub const tfsr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b000 };
1201 /// D19.2.146 TPIDR2_EL0, EL0 Read/Write Software Thread ID Register 2
1202 pub const tpidr2_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b101 };
1203 /// D19.2.147 TPIDR_EL0, EL0 Read/Write Software Thread ID Register
1204 pub const tpidr_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b010 };
1205 /// D19.2.148 TPIDR_EL1, EL1 Read/Write Software Thread ID Register
1206 pub const tpidr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b100 };
1207 /// D19.2.149 TPIDR_EL2, EL2 Read/Write Software Thread ID Register
1208 pub const tpidr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b010 };
1209 /// D19.2.150 TPIDR_EL3, EL3 Read/Write Software Thread ID Register
1210 pub const tpidr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b010 };
1211 /// D19.2.151 TPIDRRO_EL0, EL0 Read-Only Software Thread ID Register
1212 pub const tpidrro_el3: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b011 };
1213 /// D19.2.152 TTBR0_EL1, Translation Table Base Register 0 (EL1)
1214 pub const ttbr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b000 };
1215 /// D19.2.152 TTBR0_EL12, Translation Table Base Register 0 (EL12)
1216 pub const ttbr0_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b000 };
1217 /// D19.2.153 TTBR0_EL2, Translation Table Base Register 0 (EL2)
1218 pub const ttbr0_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b000 };
1219 /// D19.2.154 TTBR0_EL3, Translation Table Base Register 0 (EL3)
1220 pub const ttbr0_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b000 };
1221 /// D19.2.155 TTBR1_EL1, Translation Table Base Register 1 (EL1)
1222 pub const ttbr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b001 };
1223 /// D19.2.155 TTBR1_EL12, Translation Table Base Register 1 (EL12)
1224 pub const ttbr1_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b001 };
1225 /// D19.2.156 TTBR1_EL2, Translation Table Base Register 1 (EL2)
1226 pub const ttbr1_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b001 };
1227 /// D19.2.157 VBAR_EL1, Vector Base Address Register (EL1)
1228 pub const vbar_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b000 };
1229 /// D19.2.157 VBAR_EL12, Vector Base Address Register (EL12)
1230 pub const vbar_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b000 };
1231 /// D19.2.158 VBAR_EL2, Vector Base Address Register (EL2)
1232 pub const vbar_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b000 };
1233 /// D19.2.159 VBAR_EL3, Vector Base Address Register (EL3)
1234 pub const vbar_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b000 };
1235 /// D19.2.160 VMPIDR_EL2, Virtualization Multiprocessor ID Register
1236 pub const vmpidr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b101 };
1237 /// D19.2.161 VNCR_EL2, Virtual Nested Control Register
1238 pub const nvcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b000 };
1239 /// D19.2.162 VPIDR_EL2, Virtualization Processor ID Register
1240 pub const vpidr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b000 };
1241 /// D19.2.163 VSTCR_EL2, Virtualization Secure Translation Control Register
1242 pub const vstcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0110, .op2 = 0b010 };
1243 /// D19.2.164 VSTTBR_EL2, Virtualization Secure Translation Table Base Register
1244 pub const vsttbr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0110, .op2 = 0b000 };
1245 /// D19.2.165 VTCR_EL2, Virtualization Translation Control Register
1246 pub const vtcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b010 };
1247 /// D19.2.166 VTTBR_EL2, Virtualization Translation Table Base Register
1248 pub const vttbr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b000 };
1249 /// D19.2.167 ZCR_EL1, SVE Control Register (EL1)
1250 pub const zcr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b000 };
1251 /// D19.2.167 ZCR_EL12, SVE Control Register (EL12)
1252 pub const zcr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b000 };
1253 /// D19.2.168 ZCR_EL2, SVE Control Register (EL2)
1254 pub const zcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b000 };
1255 /// D19.2.169 ZCR_EL3, SVE Control Register (EL3)
1256 pub const zcr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b000 };
1257
1258 pub fn parse(reg: []const u8) ?System {
1259 if (reg.len >= 10 and std.ascii.toLower(reg[0]) == 's') encoded: {
1260 var symbol_it = std.mem.splitScalar(u8, reg[1..], '_');
1261 const op0 = std.fmt.parseInt(u2, symbol_it.next() orelse break :encoded, 10) catch break :encoded;
1262 if (op0 < 0b10) break :encoded;
1263 const op1 = std.fmt.parseInt(u3, symbol_it.next() orelse break :encoded, 10) catch break :encoded;
1264 const n = symbol_it.next() orelse break :encoded;
1265 if (n.len == 0 or std.ascii.toLower(n[0]) != 'c') break :encoded;
1266 const CRn = std.fmt.parseInt(u4, n[1..], 10) catch break :encoded;
1267 const m = symbol_it.next() orelse break :encoded;
1268 if (m.len == 0 or std.ascii.toLower(m[0]) != 'c') break :encoded;
1269 const CRm = std.fmt.parseInt(u4, m[1..], 10) catch break :encoded;
1270 const op2 = std.fmt.parseInt(u3, symbol_it.next() orelse break :encoded, 10) catch break :encoded;
1271 if (symbol_it.next() != null) break :encoded;
1272 return .{ .op0 = op0, .op1 = op1, .CRn = CRn, .CRm = CRm, .op2 = op2 };
1273 }
1274 inline for (@typeInfo(System).@"struct".decls) |decl| {
1275 if (@TypeOf(@field(System, decl.name)) != System) continue;
1276 if (toLowerEqlAssertLower(reg, decl.name)) return @field(System, decl.name);
1277 }
1278 return null;
1279 }
1280 };
1281
1282 fn toLowerEqlAssertLower(lhs: []const u8, rhs: []const u8) bool {
1283 if (lhs.len != rhs.len) return false;
1284 for (lhs, rhs) |l, r| {
1285 assert(!std.ascii.isUpper(r));
1286 if (std.ascii.toLower(l) != r) return false;
1287 }
1288 return true;
1289 }
1290};
1291
1292/// C1.2.4 Condition code
1293pub const ConditionCode = enum(u4) {
1294 /// integer: Equal
1295 /// floating-point: Equal
1296 /// Z == 1
1297 eq = 0b0000,
1298 /// integer: Not equal
1299 /// floating-point: Not equal or unordered
1300 /// Z == 0
1301 ne = 0b0001,
1302 /// integer: Unsigned higher or same
1303 /// floating-point: Greater than, equal, or unordered
1304 /// C == 1
1305 hs = 0b0010,
1306 /// integer: Unsigned lower
1307 /// floating-point: Less than
1308 /// C == 0
1309 lo = 0b0011,
1310 /// integer: Minus, negative
1311 /// floating-point: Less than
1312 /// N == 1
1313 mi = 0b0100,
1314 /// integer: Plus, positive or zero
1315 /// floating-point: Greater than, equal, or unordered
1316 /// N == 0
1317 pl = 0b0101,
1318 /// integer: Overflow
1319 /// floating-point: Unordered
1320 /// V == 1
1321 vs = 0b0110,
1322 /// integer: No overflow
1323 /// floating-point: Ordered
1324 /// V == 0
1325 vc = 0b0111,
1326 /// integer: Unsigned higher
1327 /// floating-point: Greater than, or unordered
1328 /// C == 1 and Z == 0
1329 hi = 0b1000,
1330 /// integer: Unsigned lower or same
1331 /// floating-point: Less than or equal
1332 /// C == 0 or Z == 1
1333 ls = 0b1001,
1334 /// integer: Signed greater than or equal
1335 /// floating-point: Greater than or equal
1336 /// N == V
1337 ge = 0b1010,
1338 /// integer: Signed less than
1339 /// floating-point: Less than, or unordered
1340 /// N != V
1341 lt = 0b1011,
1342 /// integer: Signed greater than
1343 /// floating-point: Greater than
1344 /// Z == 0 and N == V
1345 gt = 0b1100,
1346 /// integer: Signed less than or equal
1347 /// floating-point: Less than, equal, or unordered
1348 /// Z == 1 or N != V
1349 le = 0b1101,
1350 /// integer: Always
1351 /// floating-point: Always
1352 /// true
1353 al = 0b1110,
1354 /// integer: Always
1355 /// floating-point: Always
1356 /// true
1357 nv = 0b1111,
1358 /// Carry set
1359 /// C == 1
1360 pub const cs: ConditionCode = .hs;
1361 /// Carry clear
1362 /// C == 0
1363 pub const cc: ConditionCode = .lo;
1364
1365 pub fn invert(cond: ConditionCode) ConditionCode {
1366 return @enumFromInt(@intFromEnum(cond) ^ 0b0001);
1367 }
1368};
1369
1370/// C4.1 A64 instruction set encoding
1371pub const Instruction = packed union {
1372 group: Group,
1373 reserved: Reserved,
1374 sme: Sme,
1375 sve: Sve,
1376 data_processing_immediate: DataProcessingImmediate,
1377 branch_exception_generating_system: BranchExceptionGeneratingSystem,
1378 load_store: LoadStore,
1379 data_processing_register: DataProcessingRegister,
1380 data_processing_vector: DataProcessingVector,
1381
1382 /// Table C4-1 Main encoding table for the A64 instruction set
1383 pub const Group = packed struct {
1384 encoded0: u25,
1385 op1: u4,
1386 encoded29: u2,
1387 op0: u1,
1388 };
1389
1390 /// C4.1.1 Reserved
1391 pub const Reserved = packed union {
1392 group: @This().Group,
1393 udf: Udf,
1394
1395 /// Table C4-2 Encoding table for the Reserved group
1396 pub const Group = packed struct {
1397 encoded0: u16,
1398 op1: u9,
1399 decoded25: u4 = 0b0000,
1400 op0: u2,
1401 decoded31: u1 = 0b0,
1402 };
1403
1404 /// C6.2.387 UDF
1405 pub const Udf = packed struct {
1406 imm16: u16,
1407 decoded16: u16 = 0b0000000000000000,
1408 };
1409
1410 pub const Decoded = union(enum) {
1411 unallocated,
1412 udf: Udf,
1413 };
1414 pub fn decode(inst: @This()) @This().Decoded {
1415 return switch (inst.group.op0) {
1416 0b00 => switch (inst.group.op1) {
1417 0b000000000 => .{ .udf = inst.udf },
1418 else => .unallocated,
1419 },
1420 else => .unallocated,
1421 };
1422 }
1423 };
1424
1425 /// C4.1.2 SME encodings
1426 pub const Sme = packed union {
1427 group: @This().Group,
1428
1429 /// Table C4-3 Encodings table for the SME encodings group
1430 pub const Group = packed struct {
1431 encoded0: u2,
1432 op2: u3,
1433 encoded5: u5,
1434 op1: u15,
1435 decoded25: u4 = 0b0000,
1436 op0: u2,
1437 decoded31: u1 = 0b1,
1438 };
1439 };
1440
1441 /// C4.1.30 SVE encodings
1442 pub const Sve = packed union {
1443 group: @This().Group,
1444
1445 /// Table C4-31 Encoding table for the SVE encodings group
1446 pub const Group = packed struct {
1447 encoded0: u4,
1448 op2: u1,
1449 encoded5: u5,
1450 op1: u15,
1451 decoded25: u4 = 0b0010,
1452 op0: u3,
1453 };
1454 };
1455
1456 /// C4.1.86 Data Processing -- Immediate
1457 pub const DataProcessingImmediate = packed union {
1458 group: @This().Group,
1459 pc_relative_addressing: PcRelativeAddressing,
1460 add_subtract_immediate: AddSubtractImmediate,
1461 add_subtract_immediate_with_tags: AddSubtractImmediateWithTags,
1462 logical_immediate: LogicalImmediate,
1463 move_wide_immediate: MoveWideImmediate,
1464 bitfield: Bitfield,
1465 extract: Extract,
1466
1467 /// Table C4-87 Encoding table for the Data Processing -- Immediate group
1468 pub const Group = packed struct {
1469 encoded0: u23,
1470 op0: u3,
1471 decoded26: u3 = 0b100,
1472 encoded29: u3,
1473 };
1474
1475 /// PC-rel. addressing
1476 pub const PcRelativeAddressing = packed union {
1477 group: @This().Group,
1478 adr: Adr,
1479 adrp: Adrp,
1480
1481 pub const Group = packed struct {
1482 Rd: Register.Encoded,
1483 immhi: i19,
1484 decoded24: u5 = 0b10000,
1485 immlo: u2,
1486 op: Op,
1487 };
1488
1489 /// C6.2.10 ADR
1490 pub const Adr = packed struct {
1491 Rd: Register.Encoded,
1492 immhi: i19,
1493 decoded24: u5 = 0b10000,
1494 immlo: u2,
1495 op: Op = .adr,
1496 };
1497
1498 /// C6.2.11 ADRP
1499 pub const Adrp = packed struct {
1500 Rd: Register.Encoded,
1501 immhi: i19,
1502 decoded24: u5 = 0b10000,
1503 immlo: u2,
1504 op: Op = .adrp,
1505 };
1506
1507 pub const Op = enum(u1) {
1508 adr = 0b0,
1509 adrp = 0b1,
1510 };
1511
1512 pub const Decoded = union(enum) {
1513 adr: Adr,
1514 adrp: Adrp,
1515 };
1516 pub fn decode(inst: @This()) @This().Decoded {
1517 return switch (inst.group.op) {
1518 .adr => .{ .adr = inst.adr },
1519 .adrp => .{ .adrp = inst.adrp },
1520 };
1521 }
1522 };
1523
1524 /// Add/subtract (immediate)
1525 pub const AddSubtractImmediate = packed union {
1526 group: @This().Group,
1527 add: Add,
1528 adds: Adds,
1529 sub: Sub,
1530 subs: Subs,
1531
1532 pub const Group = packed struct {
1533 Rd: Register.Encoded,
1534 Rn: Register.Encoded,
1535 imm12: u12,
1536 sh: Shift,
1537 decoded23: u6 = 0b100010,
1538 S: bool,
1539 op: AddSubtractOp,
1540 sf: Register.GeneralSize,
1541 };
1542
1543 /// C6.2.4 ADD (immediate)
1544 pub const Add = packed struct {
1545 Rd: Register.Encoded,
1546 Rn: Register.Encoded,
1547 imm12: u12,
1548 sh: Shift,
1549 decoded23: u6 = 0b100010,
1550 S: bool = false,
1551 op: AddSubtractOp = .add,
1552 sf: Register.GeneralSize,
1553 };
1554
1555 /// C6.2.8 ADDS (immediate)
1556 pub const Adds = packed struct {
1557 Rd: Register.Encoded,
1558 Rn: Register.Encoded,
1559 imm12: u12,
1560 sh: Shift,
1561 decoded23: u6 = 0b100010,
1562 S: bool = true,
1563 op: AddSubtractOp = .add,
1564 sf: Register.GeneralSize,
1565 };
1566
1567 /// C6.2.357 SUB (immediate)
1568 pub const Sub = packed struct {
1569 Rd: Register.Encoded,
1570 Rn: Register.Encoded,
1571 imm12: u12,
1572 sh: Shift,
1573 decoded23: u6 = 0b100010,
1574 S: bool = false,
1575 op: AddSubtractOp = .sub,
1576 sf: Register.GeneralSize,
1577 };
1578
1579 /// C6.2.363 SUBS (immediate)
1580 pub const Subs = packed struct {
1581 Rd: Register.Encoded,
1582 Rn: Register.Encoded,
1583 imm12: u12,
1584 sh: Shift,
1585 decoded23: u6 = 0b100010,
1586 S: bool = true,
1587 op: AddSubtractOp = .sub,
1588 sf: Register.GeneralSize,
1589 };
1590
1591 pub const Shift = enum(u1) {
1592 @"0" = 0b0,
1593 @"12" = 0b1,
1594 };
1595
1596 pub const Decoded = union(enum) {
1597 add: Add,
1598 adds: Adds,
1599 sub: Sub,
1600 subs: Subs,
1601 };
1602 pub fn decode(inst: @This()) @This().Decaded {
1603 return switch (inst.group.op) {
1604 .add => switch (inst.group.S) {
1605 false => .{ .add = inst.add },
1606 true => .{ .addc = inst.addc },
1607 },
1608 .sub => switch (inst.group.S) {
1609 false => .{ .sub = inst.sub },
1610 true => .{ .subc = inst.subc },
1611 },
1612 };
1613 }
1614 };
1615
1616 /// Add/subtract (immediate, with tags)
1617 pub const AddSubtractImmediateWithTags = packed union {
1618 group: @This().Group,
1619 addg: Addg,
1620 subg: Subg,
1621
1622 pub const Group = packed struct {
1623 Rd: Register.Encoded,
1624 Rn: Register.Encoded,
1625 uimm4: u4,
1626 op3: u2,
1627 uimm6: u6,
1628 o2: u1,
1629 decoded23: u6 = 0b100011,
1630 S: bool,
1631 op: AddSubtractOp,
1632 sf: Register.GeneralSize,
1633 };
1634
1635 /// C6.2.6 ADDG
1636 pub const Addg = packed struct {
1637 Xd: Register.Encoded,
1638 Xn: Register.Encoded,
1639 uimm4: u4,
1640 op3: u2 = 0b00,
1641 uimm6: u6,
1642 o2: u1 = 0b0,
1643 decoded23: u6 = 0b100011,
1644 S: bool = false,
1645 op: AddSubtractOp = .add,
1646 sf: Register.GeneralSize = .doubleword,
1647 };
1648
1649 /// C6.2.359 SUBG
1650 pub const Subg = packed struct {
1651 Xd: Register.Encoded,
1652 Xn: Register.Encoded,
1653 uimm4: u4,
1654 op3: u2 = 0b00,
1655 uimm6: u6,
1656 o2: u1 = 0b0,
1657 decoded23: u6 = 0b100011,
1658 S: bool = false,
1659 op: AddSubtractOp = .sub,
1660 sf: Register.GeneralSize = .doubleword,
1661 };
1662
1663 pub const Decoded = union(enum) {
1664 unallocated,
1665 addg: Addg,
1666 subg: Subg,
1667 };
1668 pub fn decode(inst: @This()) @This().Decoded {
1669 return switch (inst.group.o2) {
1670 0b1 => .unallocated,
1671 0b0 => switch (inst.group.sf) {
1672 .word => .unallocated,
1673 .doubleword => switch (inst.group.S) {
1674 true => .unallocated,
1675 false => switch (inst.group.op) {
1676 .add => .{ .addg = inst.addg },
1677 .sub => .{ .subg = inst.subg },
1678 },
1679 },
1680 },
1681 };
1682 }
1683 };
1684
1685 /// Logical (immediate)
1686 pub const LogicalImmediate = packed union {
1687 group: @This().Group,
1688 @"and": And,
1689 orr: Orr,
1690 eor: Eor,
1691 ands: Ands,
1692
1693 pub const Group = packed struct {
1694 Rd: Register.Encoded,
1695 Rn: Register.Encoded,
1696 imm: Bitmask,
1697 decoded23: u6 = 0b100100,
1698 opc: LogicalOpc,
1699 sf: Register.GeneralSize,
1700 };
1701
1702 /// C6.2.12 AND (immediate)
1703 pub const And = packed struct {
1704 Rd: Register.Encoded,
1705 Rn: Register.Encoded,
1706 imm: Bitmask,
1707 decoded23: u6 = 0b100100,
1708 opc: LogicalOpc = .@"and",
1709 sf: Register.GeneralSize,
1710 };
1711
1712 /// C6.2.240 ORR (immediate)
1713 pub const Orr = packed struct {
1714 Rd: Register.Encoded,
1715 Rn: Register.Encoded,
1716 imm: Bitmask,
1717 decoded23: u6 = 0b100100,
1718 opc: LogicalOpc = .orr,
1719 sf: Register.GeneralSize,
1720 };
1721
1722 /// C6.2.119 EOR (immediate)
1723 pub const Eor = packed struct {
1724 Rd: Register.Encoded,
1725 Rn: Register.Encoded,
1726 imm: Bitmask,
1727 decoded23: u6 = 0b100100,
1728 opc: LogicalOpc = .eor,
1729 sf: Register.GeneralSize,
1730 };
1731
1732 /// C6.2.14 ANDS (immediate)
1733 pub const Ands = packed struct {
1734 Rd: Register.Encoded,
1735 Rn: Register.Encoded,
1736 imm: Bitmask,
1737 decoded23: u6 = 0b100100,
1738 opc: LogicalOpc = .ands,
1739 sf: Register.GeneralSize,
1740 };
1741
1742 pub const Decoded = union(enum) {
1743 unallocated,
1744 @"and": And,
1745 orr: Orr,
1746 eor: Eor,
1747 ands: Ands,
1748 };
1749 pub fn decode(inst: @This()) @This().Decoded {
1750 return if (!inst.group.imm.validImmediate(inst.group.sf))
1751 .unallocated
1752 else switch (inst.group.opc) {
1753 .@"and" => .{ .@"and" = inst.@"and" },
1754 .orr => .{ .orr = inst.orr },
1755 .eor => .{ .eor = inst.eor },
1756 .ands => .{ .ands = inst.ands },
1757 };
1758 }
1759 };
1760
1761 /// Move wide (immediate)
1762 pub const MoveWideImmediate = packed union {
1763 group: @This().Group,
1764 movn: Movn,
1765 movz: Movz,
1766 movk: Movk,
1767
1768 pub const Group = packed struct {
1769 Rd: Register.Encoded,
1770 imm16: u16,
1771 hw: Hw,
1772 decoded23: u6 = 0b100101,
1773 opc: Opc,
1774 sf: Register.GeneralSize,
1775 };
1776
1777 /// C6.2.226 MOVN
1778 pub const Movn = packed struct {
1779 Rd: Register.Encoded,
1780 imm16: u16,
1781 hw: Hw,
1782 decoded23: u6 = 0b100101,
1783 opc: Opc = .movn,
1784 sf: Register.GeneralSize,
1785 };
1786
1787 /// C6.2.227 MOVZ
1788 pub const Movz = packed struct {
1789 Rd: Register.Encoded,
1790 imm16: u16,
1791 hw: Hw,
1792 decoded23: u6 = 0b100101,
1793 opc: Opc = .movz,
1794 sf: Register.GeneralSize,
1795 };
1796
1797 /// C6.2.225 MOVK
1798 pub const Movk = packed struct {
1799 Rd: Register.Encoded,
1800 imm16: u16,
1801 hw: Hw,
1802 decoded23: u6 = 0b100101,
1803 opc: Opc = .movk,
1804 sf: Register.GeneralSize,
1805 };
1806
1807 pub const Hw = enum(u2) {
1808 @"0" = 0b00,
1809 @"16" = 0b01,
1810 @"32" = 0b10,
1811 @"48" = 0b11,
1812
1813 pub fn int(hw: Hw) u6 {
1814 return switch (hw) {
1815 .@"0" => 0,
1816 .@"16" => 16,
1817 .@"32" => 32,
1818 .@"48" => 48,
1819 };
1820 }
1821
1822 pub fn sf(hw: Hw) Register.GeneralSize {
1823 return switch (hw) {
1824 .@"0", .@"16" => .word,
1825 .@"32", .@"48" => .doubleword,
1826 };
1827 }
1828 };
1829
1830 pub const Opc = enum(u2) {
1831 movn = 0b00,
1832 movz = 0b10,
1833 movk = 0b11,
1834 _,
1835 };
1836
1837 pub const Decoded = union(enum) {
1838 unallocated,
1839 movn: Movn,
1840 movz: Movz,
1841 movk: Movk,
1842 };
1843 pub fn decode(inst: @This()) @This().Decoded {
1844 return if (inst.group.sf == .word and inst.group.hw.sf() == .doubleword)
1845 .unallocated
1846 else switch (inst.group.opc) {
1847 _ => .unallocated,
1848 .movn => .{ .movn = inst.movn },
1849 .movz => .{ .movz = inst.movz },
1850 .movk => .{ .movk = inst.movk },
1851 };
1852 }
1853 };
1854
1855 /// Bitfield
1856 pub const Bitfield = packed union {
1857 group: @This().Group,
1858 sbfm: Sbfm,
1859 bfm: Bfm,
1860 ubfm: Ubfm,
1861
1862 pub const Group = packed struct {
1863 Rd: Register.Encoded,
1864 Rn: Register.Encoded,
1865 imm: Bitmask,
1866 decoded23: u6 = 0b100110,
1867 opc: Opc,
1868 sf: Register.GeneralSize,
1869 };
1870
1871 pub const Sbfm = packed struct {
1872 Rd: Register.Encoded,
1873 Rn: Register.Encoded,
1874 imm: Bitmask,
1875 decoded23: u6 = 0b100110,
1876 opc: Opc = .sbfm,
1877 sf: Register.GeneralSize,
1878 };
1879
1880 pub const Bfm = packed struct {
1881 Rd: Register.Encoded,
1882 Rn: Register.Encoded,
1883 imm: Bitmask,
1884 decoded23: u6 = 0b100110,
1885 opc: Opc = .bfm,
1886 sf: Register.GeneralSize,
1887 };
1888
1889 pub const Ubfm = packed struct {
1890 Rd: Register.Encoded,
1891 Rn: Register.Encoded,
1892 imm: Bitmask,
1893 decoded23: u6 = 0b100110,
1894 opc: Opc = .ubfm,
1895 sf: Register.GeneralSize,
1896 };
1897
1898 pub const Opc = enum(u2) {
1899 sbfm = 0b00,
1900 bfm = 0b01,
1901 ubfm = 0b10,
1902 _,
1903 };
1904
1905 pub const Decoded = union(enum) {
1906 unallocated,
1907 sbfm: Sbfm,
1908 bfm: Bfm,
1909 ubfm: Ubfm,
1910 };
1911 pub fn decode(inst: @This()) @This().Decoded {
1912 return if (!inst.group.imm.validBitfield(inst.group.sf))
1913 .unallocated
1914 else switch (inst.group.opc) {
1915 _ => .unallocated,
1916 .sbfm => .{ .sbfm = inst.sbfm },
1917 .bfm => .{ .bfm = inst.bfm },
1918 .ubfm => .{ .ubfm = inst.ubfm },
1919 };
1920 }
1921 };
1922
1923 /// Extract
1924 pub const Extract = packed union {
1925 group: @This().Group,
1926 extr: Extr,
1927
1928 pub const Group = packed struct {
1929 Rd: Register.Encoded,
1930 Rn: Register.Encoded,
1931 imms: u6,
1932 Rm: Register.Encoded,
1933 o0: u1,
1934 N: Register.GeneralSize,
1935 decoded23: u6 = 0b100111,
1936 op21: u2,
1937 sf: Register.GeneralSize,
1938 };
1939
1940 pub const Extr = packed struct {
1941 Rd: Register.Encoded,
1942 Rn: Register.Encoded,
1943 imms: u6,
1944 Rm: Register.Encoded,
1945 o0: u1 = 0b0,
1946 N: Register.GeneralSize,
1947 decoded23: u6 = 0b100111,
1948 op21: u2 = 0b00,
1949 sf: Register.GeneralSize,
1950 };
1951
1952 pub const Decoded = union(enum) {
1953 unallocated,
1954 extr: Extr,
1955 };
1956 pub fn decode(inst: @This()) @This().Decoded {
1957 return switch (inst.group.op21) {
1958 0b01, 0b10...0b11 => .unallocated,
1959 0b00 => switch (inst.group.o0) {
1960 0b1 => .unallocated,
1961 0b0 => if ((inst.group.sf == .word and @as(u1, @truncate(inst.group.imms >> 5)) == 0b1) or
1962 inst.group.sf != inst.group.N)
1963 .unallocated
1964 else
1965 .{ .extr = inst.extr },
1966 },
1967 };
1968 }
1969 };
1970
1971 pub const Bitmask = packed struct {
1972 imms: u6,
1973 immr: u6,
1974 N: Register.GeneralSize,
1975
1976 fn lenHsb(bitmask: Bitmask) u7 {
1977 return @bitCast(packed struct {
1978 not_imms: u6,
1979 N: Register.GeneralSize,
1980 }{ .not_imms = ~bitmask.imms, .N = bitmask.N });
1981 }
1982
1983 fn validImmediate(bitmask: Bitmask, sf: Register.GeneralSize) bool {
1984 if (sf == .word and bitmask.N == .doubleword) return false;
1985 const len_hsb = bitmask.lenHsb();
1986 return (len_hsb -% 1) & len_hsb != 0b0_000000;
1987 }
1988
1989 fn validBitfield(bitmask: Bitmask, sf: Register.GeneralSize) bool {
1990 if (sf != bitmask.N) return false;
1991 if (sf == .word and (@as(u1, @truncate(bitmask.immr >> 5)) != 0b0 or
1992 @as(u1, @truncate(bitmask.imms >> 5)) != 0b0)) return false;
1993 const len_hsb = bitmask.lenHsb();
1994 return len_hsb >= 0b0_000010;
1995 }
1996
1997 fn decode(bitmask: Bitmask, sf: Register.GeneralSize) struct { u64, u64 } {
1998 const esize = @as(u7, 1 << 6) >> @clz(bitmask.lenHsb());
1999 const levels: u6 = @intCast(esize - 1);
2000 const s = bitmask.imms & levels;
2001 const r = bitmask.immr & levels;
2002 const d = (s -% r) & levels;
2003 const welem = @as(u64, std.math.maxInt(u64)) >> (63 - s);
2004 const telem = @as(u64, std.math.maxInt(u64)) >> (63 - d);
2005 const emask = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - esize);
2006 const rmask = @divExact(std.math.maxInt(u64), emask);
2007 const wmask = std.math.rotr(u64, welem * rmask, r);
2008 const tmask = telem * rmask;
2009 return switch (sf) {
2010 .word => .{ @as(u32, @truncate(wmask)), @as(u32, @truncate(tmask)) },
2011 .doubleword => .{ wmask, tmask },
2012 };
2013 }
2014
2015 pub fn decodeImmediate(bitmask: Bitmask, sf: Register.GeneralSize) u64 {
2016 assert(bitmask.validImmediate(sf));
2017 const imm, _ = bitmask.decode(sf);
2018 return imm;
2019 }
2020
2021 pub fn decodeBitfield(bitmask: Bitmask, sf: Register.GeneralSize) struct { u64, u64 } {
2022 assert(bitmask.validBitfield(sf));
2023 return bitmask.decode(sf);
2024 }
2025
2026 pub fn moveWidePreferred(bitmask: Bitmask, sf: Register.GeneralSize) bool {
2027 const s = bitmask.imms;
2028 const r = bitmask.immr;
2029 const width: u7 = switch (sf) {
2030 .word => 32,
2031 .doubleword => 64,
2032 };
2033 if (sf != bitmask.N) return false;
2034 if (sf == .word and @as(u1, @truncate(s >> 5)) != 0b0) return false;
2035 if (s < 16) return (-%r % 16) <= (15 - s);
2036 if (s >= width - 15) return (r % 16) <= (s - (width - 15));
2037 return false;
2038 }
2039 };
2040
2041 pub const Decoded = union(enum) {
2042 unallocated,
2043 pc_relative_addressing: PcRelativeAddressing,
2044 add_subtract_immediate: AddSubtractImmediate,
2045 add_subtract_immediate_with_tags: AddSubtractImmediateWithTags,
2046 logical_immediate: LogicalImmediate,
2047 move_wide_immediate: MoveWideImmediate,
2048 bitfield: Bitfield,
2049 extract: Extract,
2050 };
2051 pub fn decode(inst: @This()) @This().Decoded {
2052 return switch (inst.group.op0) {
2053 0b000, 0b001 => .{ .pc_relative_addressing = inst.pc_relative_addressing },
2054 0b010 => .{ .add_subtract_immediate = inst.add_subtract_immediate },
2055 0b011 => .{ .add_subtract_immediate_with_tags = inst.add_subtract_immediate_with_tags },
2056 0b100 => .{ .logical_immediate = inst.logical_immediate },
2057 0b101 => .{ .move_wide_immediate = inst.move_wide_immediate },
2058 0b110 => .{ .bitfield = inst.bitfield },
2059 0b111 => .{ .extract = inst.extract },
2060 };
2061 }
2062 };
2063
2064 /// C4.1.87 Branches, Exception Generating and System instructions
2065 pub const BranchExceptionGeneratingSystem = packed union {
2066 group: @This().Group,
2067 conditional_branch_immediate: ConditionalBranchImmediate,
2068 exception_generating: ExceptionGenerating,
2069 system_register_argument: SystemRegisterArgument,
2070 hints: Hints,
2071 barriers: Barriers,
2072 pstate: Pstate,
2073 system_result: SystemResult,
2074 system: System,
2075 system_register_move: SystemRegisterMove,
2076 unconditional_branch_register: UnconditionalBranchRegister,
2077 unconditional_branch_immediate: UnconditionalBranchImmediate,
2078 compare_branch_immediate: CompareBranchImmediate,
2079 test_branch_immediate: TestBranchImmediate,
2080
2081 /// Table C4-88 Encoding table for the Branches, Exception Generating and System instructions group
2082 pub const Group = packed struct {
2083 op2: u5,
2084 encoded5: u7,
2085 op1: u14,
2086 decoded26: u3 = 0b101,
2087 op0: u3,
2088 };
2089
2090 /// Conditional branch (immediate)
2091 pub const ConditionalBranchImmediate = packed union {
2092 group: @This().Group,
2093 b: B,
2094 bc: Bc,
2095
2096 pub const Group = packed struct {
2097 cond: ConditionCode,
2098 o0: u1,
2099 imm19: i19,
2100 o1: u1,
2101 decoded25: u7 = 0b0101010,
2102 };
2103
2104 /// C6.2.26 B.cond
2105 pub const B = packed struct {
2106 cond: ConditionCode,
2107 o0: u1 = 0b0,
2108 imm19: i19,
2109 o1: u1 = 0b0,
2110 decoded25: u7 = 0b0101010,
2111 };
2112
2113 /// C6.2.27 BC.cond
2114 pub const Bc = packed struct {
2115 cond: ConditionCode,
2116 o0: u1 = 0b1,
2117 imm19: i19,
2118 o1: u1 = 0b0,
2119 decoded25: u7 = 0b0101010,
2120 };
2121
2122 pub const Decoded = union(enum) {
2123 unallocated,
2124 b: B,
2125 bc: Bc,
2126 };
2127 pub fn decode(inst: @This()) @This().Decoded {
2128 return switch (inst.group.o1) {
2129 0b0 => switch (inst.group.o0) {
2130 0b0 => .{ .b = inst.b },
2131 0b1 => .{ .bc = inst.bc },
2132 },
2133 0b1 => .unallocated,
2134 };
2135 }
2136 };
2137
2138 /// Exception generating
2139 pub const ExceptionGenerating = packed union {
2140 group: @This().Group,
2141 svc: Svc,
2142 hvc: Hvc,
2143 smc: Smc,
2144 brk: Brk,
2145 hlt: Hlt,
2146 tcancel: Tcancel,
2147 dcps1: Dcps1,
2148 dcps2: Dcps2,
2149 dcps3: Dcps3,
2150
2151 pub const Group = packed struct {
2152 LL: u2,
2153 op2: u3,
2154 imm16: u16,
2155 opc: u3,
2156 decoded24: u8 = 0b11010100,
2157 };
2158
2159 /// C6.2.365 SVC
2160 pub const Svc = packed struct {
2161 decoded0: u2 = 0b01,
2162 decoded2: u3 = 0b000,
2163 imm16: u16,
2164 decoded21: u3 = 0b000,
2165 decoded24: u8 = 0b11010100,
2166 };
2167
2168 /// C6.2.128 HVC
2169 pub const Hvc = packed struct {
2170 decoded0: u2 = 0b10,
2171 decoded2: u3 = 0b000,
2172 imm16: u16,
2173 decoded21: u3 = 0b000,
2174 decoded24: u8 = 0b11010100,
2175 };
2176
2177 /// C6.2.283 SMC
2178 pub const Smc = packed struct {
2179 decoded0: u2 = 0b11,
2180 decoded2: u3 = 0b000,
2181 imm16: u16,
2182 decoded21: u3 = 0b000,
2183 decoded24: u8 = 0b11010100,
2184 };
2185
2186 /// C6.2.40 BRK
2187 pub const Brk = packed struct {
2188 decoded0: u2 = 0b00,
2189 decoded2: u3 = 0b000,
2190 imm16: u16,
2191 decoded21: u3 = 0b001,
2192 decoded24: u8 = 0b11010100,
2193 };
2194
2195 /// C6.2.127 HLT
2196 pub const Hlt = packed struct {
2197 decoded0: u2 = 0b00,
2198 decoded2: u3 = 0b000,
2199 imm16: u16,
2200 decoded21: u3 = 0b010,
2201 decoded24: u8 = 0b11010100,
2202 };
2203
2204 /// C6.2.376 TCANCEL
2205 pub const Tcancel = packed struct {
2206 decoded0: u2 = 0b00,
2207 decoded2: u3 = 0b000,
2208 imm16: u16,
2209 decoded21: u3 = 0b011,
2210 decoded24: u8 = 0b11010100,
2211 };
2212
2213 /// C6.2.110 DCPS1
2214 pub const Dcps1 = packed struct {
2215 LL: u2 = 0b01,
2216 decoded2: u3 = 0b000,
2217 imm16: u16,
2218 decoded21: u3 = 0b101,
2219 decoded24: u8 = 0b11010100,
2220 };
2221
2222 /// C6.2.110 DCPS2
2223 pub const Dcps2 = packed struct {
2224 LL: u2 = 0b10,
2225 decoded2: u3 = 0b000,
2226 imm16: u16,
2227 decoded21: u3 = 0b101,
2228 decoded24: u8 = 0b11010100,
2229 };
2230
2231 /// C6.2.110 DCPS3
2232 pub const Dcps3 = packed struct {
2233 LL: u2 = 0b11,
2234 decoded2: u3 = 0b000,
2235 imm16: u16,
2236 decoded21: u3 = 0b101,
2237 decoded24: u8 = 0b11010100,
2238 };
2239
2240 pub const Decoded = union(enum) {
2241 unallocated,
2242 svc: Svc,
2243 hvc: Hvc,
2244 smc: Smc,
2245 brk: Brk,
2246 hlt: Hlt,
2247 tcancel: Tcancel,
2248 dcps1: Dcps1,
2249 dcps2: Dcps2,
2250 dcps3: Dcps3,
2251 };
2252 pub fn decode(inst: @This()) @This().Decoded {
2253 return switch (inst.group.op2) {
2254 0b001 => .unallocated,
2255 0b010...0b011 => .unallocated,
2256 0b100...0b111 => .unallocated,
2257 0b000 => switch (inst.group.opc) {
2258 0b000 => switch (inst.group.LL) {
2259 0b00 => .unallocated,
2260 0b01 => .{ .svc = inst.svc },
2261 0b10 => .{ .hvc = inst.hvc },
2262 0b11 => .{ .smc = inst.smc },
2263 },
2264 0b001 => switch (inst.group.LL) {
2265 0b01 => .unallocated,
2266 0b00 => .{ .brk = inst.brk },
2267 0b10...0b11 => .unallocated,
2268 },
2269 0b010 => switch (inst.group.LL) {
2270 0b01 => .unallocated,
2271 0b00 => .{ .hlt = inst.hlt },
2272 0b10...0b11 => .unallocated,
2273 },
2274 0b011 => switch (inst.group.LL) {
2275 0b00 => .{ .tcancel = inst.tcancel },
2276 0b01 => .unallocated,
2277 0b10...0b11 => .unallocated,
2278 },
2279 0b100 => .unallocated,
2280 0b101 => switch (inst.group.LL) {
2281 0b00 => .unallocated,
2282 0b01 => .{ .dcps1 = inst.dcps1 },
2283 0b10 => .{ .dcps2 = inst.dcps2 },
2284 0b11 => .{ .dcps3 = inst.dcps3 },
2285 },
2286 0b110 => .unallocated,
2287 0b111 => .unallocated,
2288 },
2289 };
2290 }
2291 };
2292
2293 /// System instructions with register argument
2294 pub const SystemRegisterArgument = packed struct {
2295 Rt: Register.Encoded,
2296 op2: u3,
2297 CRm: u4,
2298 decoded12: u20 = 0b11010101000000110001,
2299 };
2300
2301 /// Hints
2302 pub const Hints = packed union {
2303 group: @This().Group,
2304 hint: Hint,
2305 nop: Nop,
2306 yield: Yield,
2307 wfe: Wfe,
2308 wfi: Wfi,
2309 sev: Sev,
2310 sevl: Sevl,
2311
2312 pub const Group = packed struct {
2313 decoded0: u5 = 0b11111,
2314 op2: u3,
2315 CRm: u4,
2316 decoded12: u20 = 0b11010101000000110010,
2317 };
2318
2319 /// C6.2.126 HINT
2320 pub const Hint = packed struct {
2321 decoded0: u5 = 0b11111,
2322 op2: u3,
2323 CRm: u4,
2324 decoded12: u4 = 0b0010,
2325 decoded16: u3 = 0b011,
2326 decoded19: u2 = 0b00,
2327 decoded21: u1 = 0b0,
2328 decoded22: u10 = 0b1101010100,
2329 };
2330
2331 /// C6.2.238 NOP
2332 pub const Nop = packed struct {
2333 decoded0: u5 = 0b11111,
2334 op2: u3 = 0b000,
2335 CRm: u4 = 0b0000,
2336 decoded12: u4 = 0b0010,
2337 decoded16: u3 = 0b011,
2338 decoded19: u2 = 0b00,
2339 decoded21: u1 = 0b0,
2340 decoded22: u10 = 0b1101010100,
2341 };
2342
2343 /// C6.2.402 YIELD
2344 pub const Yield = packed struct {
2345 decoded0: u5 = 0b11111,
2346 op2: u3 = 0b001,
2347 CRm: u4 = 0b0000,
2348 decoded12: u4 = 0b0010,
2349 decoded16: u3 = 0b011,
2350 decoded19: u2 = 0b00,
2351 decoded21: u1 = 0b0,
2352 decoded22: u10 = 0b1101010100,
2353 };
2354
2355 /// C6.2.396 WFE
2356 pub const Wfe = packed struct {
2357 decoded0: u5 = 0b11111,
2358 op2: u3 = 0b010,
2359 CRm: u4 = 0b0000,
2360 decoded12: u4 = 0b0010,
2361 decoded16: u3 = 0b011,
2362 decoded19: u2 = 0b00,
2363 decoded21: u1 = 0b0,
2364 decoded22: u10 = 0b1101010100,
2365 };
2366
2367 /// C6.2.398 WFI
2368 pub const Wfi = packed struct {
2369 decoded0: u5 = 0b11111,
2370 op2: u3 = 0b011,
2371 CRm: u4 = 0b0000,
2372 decoded12: u4 = 0b0010,
2373 decoded16: u3 = 0b011,
2374 decoded19: u2 = 0b00,
2375 decoded21: u1 = 0b0,
2376 decoded22: u10 = 0b1101010100,
2377 };
2378
2379 /// C6.2.280 SEV
2380 pub const Sev = packed struct {
2381 decoded0: u5 = 0b11111,
2382 op2: u3 = 0b100,
2383 CRm: u4 = 0b0000,
2384 decoded12: u4 = 0b0010,
2385 decoded16: u3 = 0b011,
2386 decoded19: u2 = 0b00,
2387 decoded21: u1 = 0b0,
2388 decoded22: u10 = 0b1101010100,
2389 };
2390
2391 /// C6.2.280 SEVL
2392 pub const Sevl = packed struct {
2393 decoded0: u5 = 0b11111,
2394 op2: u3 = 0b101,
2395 CRm: u4 = 0b0000,
2396 decoded12: u4 = 0b0010,
2397 decoded16: u3 = 0b011,
2398 decoded19: u2 = 0b00,
2399 decoded21: u1 = 0b0,
2400 decoded22: u10 = 0b1101010100,
2401 };
2402
2403 pub const Decoded = union(enum) {
2404 hint: Hint,
2405 nop: Nop,
2406 yield: Yield,
2407 wfe: Wfe,
2408 wfi: Wfi,
2409 sev: Sev,
2410 sevl: Sevl,
2411 };
2412 pub fn decode(inst: @This()) @This().Decoded {
2413 return switch (inst.group.CRm) {
2414 else => .{ .hint = inst.hint },
2415 0b0000 => switch (inst.group.op2) {
2416 else => .{ .hint = inst.hint },
2417 0b000 => .{ .nop = inst.nop },
2418 0b001 => .{ .yield = inst.yield },
2419 0b010 => .{ .wfe = inst.wfe },
2420 0b011 => .{ .wfi = inst.wfi },
2421 0b100 => .{ .sev = inst.sev },
2422 0b101 => .{ .sevl = inst.sevl },
2423 },
2424 };
2425 }
2426 };
2427
2428 /// Barriers
2429 pub const Barriers = packed union {
2430 group: @This().Group,
2431 clrex: Clrex,
2432 dsb: Dsb,
2433 dmb: Dmb,
2434 isb: Isb,
2435 sb: Sb,
2436
2437 pub const Group = packed struct {
2438 Rt: Register.Encoded,
2439 op2: u3,
2440 CRm: u4,
2441 decoded12: u4 = 0b0011,
2442 decoded16: u3 = 0b011,
2443 decoded19: u2 = 0b00,
2444 decoded21: u1 = 0b0,
2445 decoded22: u10 = 0b1101010100,
2446 };
2447
2448 /// C6.2.56 CLREX
2449 pub const Clrex = packed struct {
2450 Rt: Register.Encoded = no_reg,
2451 op2: u3 = 0b010,
2452 CRm: u4,
2453 decoded12: u4 = 0b0011,
2454 decoded16: u3 = 0b011,
2455 decoded19: u2 = 0b00,
2456 decoded21: u1 = 0b0,
2457 decoded22: u10 = 0b1101010100,
2458 };
2459
2460 /// C6.2.116 DSB
2461 pub const Dsb = packed struct {
2462 Rt: Register.Encoded = no_reg,
2463 opc: u2 = 0b00,
2464 decoded7: u1 = 0b1,
2465 CRm: Option,
2466 decoded12: u4 = 0b0011,
2467 decoded16: u3 = 0b011,
2468 decoded19: u2 = 0b00,
2469 decoded21: u1 = 0b0,
2470 decoded22: u10 = 0b1101010100,
2471 };
2472
2473 /// C6.2.114 DMB
2474 pub const Dmb = packed struct {
2475 Rt: Register.Encoded = no_reg,
2476 opc: u2 = 0b01,
2477 decoded7: u1 = 0b1,
2478 CRm: Option,
2479 decoded12: u4 = 0b0011,
2480 decoded16: u3 = 0b011,
2481 decoded19: u2 = 0b00,
2482 decoded21: u1 = 0b0,
2483 decoded22: u10 = 0b1101010100,
2484 };
2485
2486 /// C6.2.131 ISB
2487 pub const Isb = packed struct {
2488 Rt: Register.Encoded = no_reg,
2489 opc: u2 = 0b10,
2490 decoded7: u1 = 0b1,
2491 CRm: Option,
2492 decoded12: u4 = 0b0011,
2493 decoded16: u3 = 0b011,
2494 decoded19: u2 = 0b00,
2495 decoded21: u1 = 0b0,
2496 decoded22: u10 = 0b1101010100,
2497 };
2498
2499 /// C6.2.264 SB
2500 pub const Sb = packed struct {
2501 Rt: Register.Encoded = no_reg,
2502 opc: u2 = 0b11,
2503 decoded7: u1 = 0b1,
2504 CRm: u4 = 0b0000,
2505 decoded12: u4 = 0b0011,
2506 decoded16: u3 = 0b011,
2507 decoded19: u2 = 0b00,
2508 decoded21: u1 = 0b0,
2509 decoded22: u10 = 0b1101010100,
2510 };
2511
2512 pub const Option = enum(u4) {
2513 oshld = 0b0001,
2514 oshst = 0b0010,
2515 osh = 0b0011,
2516 nshld = 0b0101,
2517 nshst = 0b0110,
2518 nsh = 0b0111,
2519 ishld = 0b1001,
2520 ishst = 0b1010,
2521 ish = 0b1011,
2522 ld = 0b1101,
2523 st = 0b1110,
2524 sy = 0b1111,
2525 _,
2526 };
2527
2528 pub const Decoded = union(enum) {
2529 unallocated,
2530 clrex: Clrex,
2531 dsb: Dsb,
2532 dmb: Dmb,
2533 isb: Isb,
2534 sb: Sb,
2535 };
2536 pub fn decode(inst: @This()) @This().Decoded {
2537 return switch (inst.group.op2) {
2538 0b000, 0b001 => .unallocated,
2539 0b010 => switch (inst.group.Rt) {
2540 no_reg => .{ .clrex = inst.clrex },
2541 else => .unallocated,
2542 },
2543 0b100 => switch (inst.group.Rt) {
2544 no_reg => .{ .dsb = inst.dsb },
2545 else => .unallocated,
2546 },
2547 0b101 => switch (inst.group.Rt) {
2548 no_reg => .{ .dmb = inst.dmb },
2549 else => .unallocated,
2550 },
2551 0b110 => switch (inst.group.Rt) {
2552 no_reg => .{ .isb = inst.isb },
2553 else => .unallocated,
2554 },
2555 0b111 => switch (inst.group.Rt) {
2556 no_reg => .{ .sb = inst.sb },
2557 else => .unallocated,
2558 },
2559 };
2560 }
2561 };
2562
2563 /// PSTATE
2564 pub const Pstate = packed union {
2565 group: @This().Group,
2566 msr: Msr,
2567 cfinv: Cfinv,
2568 xaflag: Xaflag,
2569 axflag: Axflag,
2570
2571 pub const Group = packed struct {
2572 Rt: Register.Encoded,
2573 op2: u3,
2574 CRm: u4,
2575 decoded12: u4 = 0b0100,
2576 op1: u3,
2577 decoded19: u13 = 0b1101010100000,
2578 };
2579
2580 /// C6.2.229 MSR (immediate)
2581 pub const Msr = packed struct {
2582 Rt: Register.Encoded = no_reg,
2583 op2: u3,
2584 CRm: u4,
2585 decoded12: u4 = 0b0100,
2586 op1: u3,
2587 decoded19: u13 = 0b1101010100000,
2588 };
2589
2590 /// C6.2.52 CFINV
2591 pub const Cfinv = packed struct {
2592 Rt: Register.Encoded = no_reg,
2593 op2: u3 = 0b000,
2594 CRm: u4 = 0b0000,
2595 decoded12: u4 = 0b0100,
2596 op1: u3 = 0b000,
2597 decoded19: u13 = 0b1101010100000,
2598 };
2599
2600 /// C6.2.400 XAFLAG
2601 pub const Xaflag = packed struct {
2602 Rt: Register.Encoded = no_reg,
2603 op2: u3 = 0b001,
2604 CRm: u4 = 0b0000,
2605 decoded12: u4 = 0b0100,
2606 op1: u3 = 0b000,
2607 decoded19: u13 = 0b1101010100000,
2608 };
2609
2610 /// C6.2.24 AXFLAG
2611 pub const Axflag = packed struct {
2612 Rt: Register.Encoded = no_reg,
2613 op2: u3 = 0b010,
2614 CRm: u4 = 0b0000,
2615 decoded12: u4 = 0b0100,
2616 op1: u3 = 0b000,
2617 decoded19: u13 = 0b1101010100000,
2618 };
2619
2620 pub const Decoded = union(enum) {
2621 unallocated,
2622 msr: Msr,
2623 cfinv: Cfinv,
2624 xaflag: Xaflag,
2625 axflag: Axflag,
2626 };
2627 pub fn decode(inst: @This()) @This().Decoded {
2628 return switch (inst.group.Rt) {
2629 else => .unallocated,
2630 no_reg => switch (inst.group.op1) {
2631 else => .{ .msr = inst.msr },
2632 0b000 => switch (inst.group.op2) {
2633 else => .{ .msr = inst.msr },
2634 0b000 => .{ .cfinv = inst.cfinv },
2635 0b001 => .{ .xaflag = inst.xaflag },
2636 0b010 => .{ .axflag = inst.axflag },
2637 },
2638 },
2639 };
2640 }
2641 };
2642
2643 /// System with result
2644 pub const SystemResult = packed struct {
2645 Rt: Register.Encoded,
2646 op2: u3,
2647 CRm: u4,
2648 CRn: u4,
2649 op1: u3,
2650 decoded19: u13 = 0b1101010100100,
2651 };
2652
2653 /// System instructions
2654 pub const System = packed union {
2655 group: @This().Group,
2656 sys: Sys,
2657 sysl: Sysl,
2658
2659 pub const Group = packed struct {
2660 Rt: Register.Encoded,
2661 op2: u3,
2662 CRm: u4,
2663 CRn: u4,
2664 op1: u3,
2665 decoded19: u2 = 0b01,
2666 L: L,
2667 decoded22: u10 = 0b1101010100,
2668 };
2669
2670 /// C6.2.372 SYS
2671 pub const Sys = packed struct {
2672 Rt: Register.Encoded,
2673 op2: u3,
2674 CRm: u4,
2675 CRn: u4,
2676 op1: u3,
2677 decoded19: u2 = 0b01,
2678 L: L = .sys,
2679 decoded22: u10 = 0b1101010100,
2680 };
2681
2682 /// C6.2.373 SYSL
2683 pub const Sysl = packed struct {
2684 Rt: Register.Encoded,
2685 op2: u3,
2686 CRm: u4,
2687 CRn: u4,
2688 op1: u3,
2689 decoded19: u2 = 0b01,
2690 L: L = .sysl,
2691 decoded22: u10 = 0b1101010100,
2692 };
2693
2694 const L = enum(u1) {
2695 sys = 0b0,
2696 sysl = 0b1,
2697 };
2698
2699 pub const Decoded = union(enum) {
2700 sys: Sys,
2701 sysl: Sysl,
2702 };
2703 pub fn decode(inst: @This()) @This().Decoded {
2704 return switch (inst.group.L) {
2705 .sys => .{ .sys = inst.sys },
2706 .sysl => .{ .sysl = inst.sysl },
2707 };
2708 }
2709 };
2710
2711 /// System register move
2712 pub const SystemRegisterMove = packed union {
2713 group: @This().Group,
2714 msr: Msr,
2715 mrs: Mrs,
2716
2717 pub const Group = packed struct {
2718 Rt: Register.Encoded,
2719 systemreg: Register.System,
2720 L: L,
2721 decoded22: u10 = 0b1101010100,
2722 };
2723
2724 /// C6.2.230 MSR (register)
2725 pub const Msr = packed struct {
2726 Rt: Register.Encoded,
2727 systemreg: Register.System,
2728 L: L = .msr,
2729 decoded22: u10 = 0b1101010100,
2730 };
2731
2732 /// C6.2.228 MRS
2733 pub const Mrs = packed struct {
2734 Rt: Register.Encoded,
2735 systemreg: Register.System,
2736 L: L = .mrs,
2737 decoded22: u10 = 0b1101010100,
2738 };
2739
2740 pub const L = enum(u1) {
2741 msr = 0b0,
2742 mrs = 0b1,
2743 };
2744
2745 pub const Decoded = union(enum) {
2746 msr: Msr,
2747 mrs: Mrs,
2748 };
2749 pub fn decode(inst: @This()) @This().Decoded {
2750 return switch (inst.group.L) {
2751 .msr => .{ .msr = inst.msr },
2752 .mrs => .{ .mrs = inst.mrs },
2753 };
2754 }
2755 };
2756
2757 /// Unconditional branch (register)
2758 pub const UnconditionalBranchRegister = packed union {
2759 group: @This().Group,
2760 br: Br,
2761 blr: Blr,
2762 ret: Ret,
2763
2764 pub const Group = packed struct {
2765 op4: u5,
2766 Rn: Register.Encoded,
2767 op3: u6,
2768 op2: u5,
2769 opc: u4,
2770 decoded25: u7 = 0b1101011,
2771 };
2772
2773 /// C6.2.37 BR
2774 pub const Br = packed struct {
2775 Rm: Register.Encoded = @enumFromInt(0),
2776 Rn: Register.Encoded,
2777 M: bool = false,
2778 A: bool = false,
2779 decoded12: u4 = 0b0000,
2780 decoded16: u5 = 0b11111,
2781 op: u2 = 0b00,
2782 decoded23: u1 = 0b0,
2783 Z: bool = false,
2784 decoded25: u7 = 0b1101011,
2785 };
2786
2787 /// C6.2.35 BLR
2788 pub const Blr = packed struct {
2789 Rm: Register.Encoded = @enumFromInt(0),
2790 Rn: Register.Encoded,
2791 M: bool = false,
2792 A: bool = false,
2793 decoded12: u4 = 0b0000,
2794 decoded16: u5 = 0b11111,
2795 op: u2 = 0b01,
2796 decoded23: u1 = 0b0,
2797 Z: bool = false,
2798 decoded25: u7 = 0b1101011,
2799 };
2800
2801 /// C6.2.254 RET
2802 pub const Ret = packed struct {
2803 Rm: Register.Encoded = @enumFromInt(0),
2804 Rn: Register.Encoded,
2805 M: bool = false,
2806 A: bool = false,
2807 decoded12: u4 = 0b0000,
2808 decoded16: u5 = 0b11111,
2809 op: u2 = 0b10,
2810 decoded23: u1 = 0b0,
2811 Z: bool = false,
2812 decoded25: u7 = 0b1101011,
2813 };
2814
2815 pub const Decoded = union(enum) {
2816 unallocated,
2817 br: Br,
2818 blr: Blr,
2819 ret: Ret,
2820 };
2821 pub fn decode(inst: @This()) @This().Decoded {
2822 return switch (inst.group.op2) {
2823 else => .unallocated,
2824 0b11111 => switch (inst.group.opc) {
2825 0b0000 => switch (inst.group.op4) {
2826 else => .unallocated,
2827 0b00000 => .{ .br = inst.br },
2828 },
2829 0b0001 => switch (inst.group.op4) {
2830 else => .unallocated,
2831 0b00000 => .{ .blr = inst.blr },
2832 },
2833 0b0010 => switch (inst.group.op4) {
2834 else => .unallocated,
2835 0b00000 => .{ .ret = inst.ret },
2836 },
2837 else => .unallocated,
2838 },
2839 };
2840 }
2841 };
2842
2843 /// Unconditional branch (immediate)
2844 pub const UnconditionalBranchImmediate = packed union {
2845 group: @This().Group,
2846 b: B,
2847 bl: Bl,
2848
2849 pub const Group = packed struct {
2850 imm26: i26,
2851 decoded26: u5 = 0b00101,
2852 op: Op,
2853 };
2854
2855 /// C6.2.25 B
2856 pub const B = packed struct {
2857 imm26: i26,
2858 decoded26: u5 = 0b00101,
2859 op: Op = .b,
2860 };
2861
2862 /// C6.2.34 BL
2863 pub const Bl = packed struct {
2864 imm26: i26,
2865 decoded26: u5 = 0b00101,
2866 op: Op = .bl,
2867 };
2868
2869 pub const Op = enum(u1) {
2870 b = 0b0,
2871 bl = 0b1,
2872 };
2873
2874 pub const Decoded = union(enum) {
2875 b: B,
2876 bl: Bl,
2877 };
2878 pub fn decode(inst: @This()) @This().Decoded {
2879 return switch (inst.group.op) {
2880 .b => .{ .b = inst.b },
2881 .bl => .{ .bl = inst.bl },
2882 };
2883 }
2884 };
2885
2886 /// Compare and branch (immediate)
2887 pub const CompareBranchImmediate = packed union {
2888 group: @This().Group,
2889 cbz: Cbz,
2890 cbnz: Cbnz,
2891
2892 pub const Group = packed struct {
2893 Rt: Register.Encoded,
2894 imm19: i19,
2895 op: Op,
2896 decoded25: u6 = 0b011010,
2897 sf: Register.GeneralSize,
2898 };
2899
2900 /// C6.2.47 CBZ
2901 pub const Cbz = packed struct {
2902 Rt: Register.Encoded,
2903 imm19: i19,
2904 op: Op = .cbz,
2905 decoded25: u6 = 0b011010,
2906 sf: Register.GeneralSize,
2907 };
2908
2909 /// C6.2.46 CBNZ
2910 pub const Cbnz = packed struct {
2911 Rt: Register.Encoded,
2912 imm19: i19,
2913 op: Op = .cbnz,
2914 decoded25: u6 = 0b011010,
2915 sf: Register.GeneralSize,
2916 };
2917
2918 pub const Op = enum(u1) {
2919 cbz = 0b0,
2920 cbnz = 0b1,
2921 };
2922
2923 pub const Decoded = union(enum) {
2924 cbz: Cbz,
2925 cbnz: Cbnz,
2926 };
2927 pub fn decode(inst: @This()) @This().Decoded {
2928 return switch (inst.group.op) {
2929 .cbz => .{ .cbz = inst.cbz },
2930 .cbnz => .{ .cbnz = inst.cbnz },
2931 };
2932 }
2933 };
2934
2935 /// Test and branch (immediate)
2936 pub const TestBranchImmediate = packed union {
2937 group: @This().Group,
2938 tbz: Tbz,
2939 tbnz: Tbnz,
2940
2941 pub const Group = packed struct {
2942 Rt: Register.Encoded,
2943 imm14: i14,
2944 b40: u5,
2945 op: Op,
2946 decoded25: u6 = 0b011011,
2947 b5: u1,
2948 };
2949
2950 /// C6.2.375 TBZ
2951 pub const Tbz = packed struct {
2952 Rt: Register.Encoded,
2953 imm14: i14,
2954 b40: u5,
2955 op: Op = .tbz,
2956 decoded25: u6 = 0b011011,
2957 b5: u1,
2958 };
2959
2960 /// C6.2.374 TBNZ
2961 pub const Tbnz = packed struct {
2962 Rt: Register.Encoded,
2963 imm14: i14,
2964 b40: u5,
2965 op: Op = .tbnz,
2966 decoded25: u6 = 0b011011,
2967 b5: u1,
2968 };
2969
2970 pub const Op = enum(u1) {
2971 tbz = 0b0,
2972 tbnz = 0b1,
2973 };
2974
2975 pub const Decoded = union(enum) {
2976 tbz: Tbz,
2977 tbnz: Tbnz,
2978 };
2979 pub fn decode(inst: @This()) @This().Decoded {
2980 return switch (inst.group.op) {
2981 .tbz => .{ .tbz = inst.tbz },
2982 .tbnz => .{ .tbnz = inst.tbnz },
2983 };
2984 }
2985 };
2986
2987 pub const no_reg: Register.Encoded = Register.Alias.zr.encode(.{});
2988
2989 pub const Decoded = union(enum) {
2990 unallocated,
2991 conditional_branch_immediate: ConditionalBranchImmediate,
2992 exception_generating: ExceptionGenerating,
2993 system_register_argument: SystemRegisterArgument,
2994 hints: Hints,
2995 barriers: Barriers,
2996 pstate: Pstate,
2997 system_result: SystemResult,
2998 system: System,
2999 system_register_move: SystemRegisterMove,
3000 unconditional_branch_register: UnconditionalBranchRegister,
3001 unconditional_branch_immediate: UnconditionalBranchImmediate,
3002 compare_branch_immediate: CompareBranchImmediate,
3003 test_branch_immediate: TestBranchImmediate,
3004 };
3005 pub fn decode(inst: @This()) @This().Decoded {
3006 return switch (inst.group.op0) {
3007 0b010 => switch (inst.group.op1) {
3008 0b000000000000000...0b01111111111111 => .{ .conditional_branch_immediate = inst.conditional_branch_immediate },
3009 else => .unallocated,
3010 },
3011 0b110 => switch (inst.group.op1) {
3012 0b00000000000000...0b00111111111111 => .{ .exception_generating = inst.exception_generating },
3013 0b01000000110001 => .{ .system_register_argument = inst.system_register_argument },
3014 0b01000000110010 => switch (inst.group.op2) {
3015 0b11111 => .{ .hints = inst.hints },
3016 else => .unallocated,
3017 },
3018 0b01000000110011 => .{ .barriers = inst.barriers },
3019 0b01000000000100,
3020 0b01000000010100,
3021 0b01000000100100,
3022 0b01000000110100,
3023 0b01000001000100,
3024 0b01000001010100,
3025 0b01000001100100,
3026 0b01000001110100,
3027 => .{ .pstate = inst.pstate },
3028 0b01001000000000...0b01001001111111 => .{ .system_result = inst.system_result },
3029 0b01000010000000...0b01000011111111, 0b01001010000000...0b01001011111111 => .{ .system = inst.system },
3030 0b01000100000000...0b01000111111111, 0b01001100000000...0b01001111111111 => .{ .system_register_move = inst.system_register_move },
3031 0b10000000000000...0b11111111111111 => .{ .unconditional_branch_register = inst.unconditional_branch_register },
3032 else => .unallocated,
3033 },
3034 0b000, 0b100 => .{ .unconditional_branch_immediate = inst.unconditional_branch_immediate },
3035 0b001, 0b101 => switch (inst.group.op1) {
3036 0b00000000000000...0b01111111111111 => .{ .compare_branch_immediate = inst.compare_branch_immediate },
3037 0b10000000000000...0b11111111111111 => .{ .test_branch_immediate = inst.test_branch_immediate },
3038 },
3039 else => .unallocated,
3040 };
3041 }
3042 };
3043
3044 /// C4.1.88 Loads and Stores
3045 pub const LoadStore = packed union {
3046 group: @This().Group,
3047 register_literal: RegisterLiteral,
3048 memory: Memory,
3049 no_allocate_pair_offset: NoAllocatePairOffset,
3050 register_pair_post_indexed: RegisterPairPostIndexed,
3051 register_pair_offset: RegisterPairOffset,
3052 register_pair_pre_indexed: RegisterPairPreIndexed,
3053 register_unscaled_immediate: RegisterUnscaledImmediate,
3054 register_immediate_post_indexed: RegisterImmediatePostIndexed,
3055 register_unprivileged: RegisterUnprivileged,
3056 register_immediate_pre_indexed: RegisterImmediatePreIndexed,
3057 register_register_offset: RegisterRegisterOffset,
3058 register_unsigned_immediate: RegisterUnsignedImmediate,
3059
3060 /// Table C4-89 Encoding table for the Loads and Stores group
3061 pub const Group = packed struct {
3062 encoded0: u10,
3063 op4: u2,
3064 encoded12: u4,
3065 op3: u6,
3066 encoded22: u1,
3067 op2: u2,
3068 decoded25: u1 = 0b0,
3069 op1: bool,
3070 decoded27: u1 = 0b1,
3071 op0: u4,
3072 };
3073
3074 /// Load register (literal)
3075 pub const RegisterLiteral = packed union {
3076 group: @This().Group,
3077 integer: Integer,
3078 vector: Vector,
3079
3080 pub const Group = packed struct {
3081 Rt: Register.Encoded,
3082 imm19: i19,
3083 decoded24: u2 = 0b00,
3084 V: bool,
3085 decoded27: u3 = 0b011,
3086 opc: u2,
3087 };
3088
3089 pub const Integer = packed union {
3090 group: @This().Group,
3091 ldr: Ldr,
3092 ldrsw: Ldrsw,
3093 prfm: Prfm,
3094
3095 pub const Group = packed struct {
3096 Rt: Register.Encoded,
3097 imm19: i19,
3098 decoded24: u2 = 0b00,
3099 V: bool = false,
3100 decoded27: u3 = 0b011,
3101 opc: u2,
3102 };
3103
3104 /// C6.2.167 LDR (literal)
3105 pub const Ldr = packed struct {
3106 Rt: Register.Encoded,
3107 imm19: i19,
3108 decoded24: u2 = 0b00,
3109 V: bool = false,
3110 decoded27: u3 = 0b011,
3111 sf: Register.GeneralSize,
3112 opc1: u1 = 0b0,
3113 };
3114
3115 /// C6.2.179 LDRSW (literal)
3116 pub const Ldrsw = packed struct {
3117 Rt: Register.Encoded,
3118 imm19: i19,
3119 decoded24: u2 = 0b00,
3120 V: bool = false,
3121 decoded27: u3 = 0b011,
3122 opc: u2 = 0b10,
3123 };
3124
3125 /// C6.2.248 PRFM (literal)
3126 pub const Prfm = packed struct {
3127 prfop: PrfOp,
3128 imm19: i19,
3129 decoded24: u2 = 0b00,
3130 V: bool = false,
3131 decoded27: u3 = 0b011,
3132 opc: u2 = 0b11,
3133 };
3134 };
3135
3136 pub const Vector = packed union {
3137 group: @This().Group,
3138 ldr: Ldr,
3139
3140 pub const Group = packed struct {
3141 Rt: Register.Encoded,
3142 imm19: i19,
3143 decoded24: u2 = 0b00,
3144 V: bool = true,
3145 decoded27: u3 = 0b011,
3146 opc: VectorSize,
3147 };
3148
3149 /// C7.2.192 LDR (literal, SIMD&FP)
3150 pub const Ldr = packed struct {
3151 Rt: Register.Encoded,
3152 imm19: i19,
3153 decoded24: u2 = 0b00,
3154 V: bool = true,
3155 decoded27: u3 = 0b011,
3156 opc: VectorSize,
3157 };
3158 };
3159
3160 pub const Decoded = union(enum) {
3161 integer: Integer,
3162 vector: Vector,
3163 };
3164 pub fn decode(inst: @This()) @This().Decoded {
3165 return switch (inst.group.V) {
3166 false => .{ .integer = inst.integer },
3167 true => .{ .vector = inst.vector },
3168 };
3169 }
3170 };
3171
3172 /// Memory Copy and Memory Set
3173 pub const Memory = packed struct {
3174 Rd: Register.Encoded,
3175 Rn: Register.Encoded,
3176 decoded10: u2 = 0b01,
3177 op2: u4,
3178 Rs: Register.Encoded,
3179 decoded21: u1 = 0b0,
3180 op1: u2,
3181 decoded24: u2 = 0b01,
3182 o0: u1,
3183 decoded27: u3 = 0b011,
3184 size: Size,
3185 };
3186
3187 /// Load/store no-allocate pair (offset)
3188 pub const NoAllocatePairOffset = packed struct {
3189 Rt: Register.Encoded,
3190 Rn: Register.Encoded,
3191 Rt2: Register.Encoded,
3192 imm7: i7,
3193 L: L,
3194 decoded23: u3 = 0b000,
3195 V: bool,
3196 decoded27: u3 = 0b101,
3197 opc: u2,
3198 };
3199
3200 /// Load/store register pair (post-indexed)
3201 pub const RegisterPairPostIndexed = packed union {
3202 group: @This().Group,
3203 integer: Integer,
3204 vector: Vector,
3205
3206 pub const Group = packed struct {
3207 Rt: Register.Encoded,
3208 Rn: Register.Encoded,
3209 Rt2: Register.Encoded,
3210 imm7: i7,
3211 L: L,
3212 decoded23: u3 = 0b001,
3213 V: bool,
3214 decoded27: u3 = 0b101,
3215 opc: u2,
3216 };
3217
3218 pub const Integer = packed union {
3219 group: @This().Group,
3220 stp: Stp,
3221 ldp: Ldp,
3222 ldpsw: Ldpsw,
3223
3224 pub const Group = packed struct {
3225 Rt: Register.Encoded,
3226 Rn: Register.Encoded,
3227 Rt2: Register.Encoded,
3228 imm7: i7,
3229 L: L,
3230 decoded23: u3 = 0b001,
3231 V: bool = false,
3232 decoded27: u3 = 0b101,
3233 opc: u2,
3234 };
3235
3236 /// C6.2.321 STP
3237 pub const Stp = packed struct {
3238 Rt: Register.Encoded,
3239 Rn: Register.Encoded,
3240 Rt2: Register.Encoded,
3241 imm7: i7,
3242 L: L = .store,
3243 decoded23: u3 = 0b001,
3244 V: bool = false,
3245 decoded27: u3 = 0b101,
3246 opc0: u1 = 0b0,
3247 sf: Register.GeneralSize,
3248 };
3249
3250 /// C6.2.164 LDP
3251 pub const Ldp = packed struct {
3252 Rt: Register.Encoded,
3253 Rn: Register.Encoded,
3254 Rt2: Register.Encoded,
3255 imm7: i7,
3256 L: L = .load,
3257 decoded23: u3 = 0b001,
3258 V: bool = false,
3259 decoded27: u3 = 0b101,
3260 opc0: u1 = 0b0,
3261 sf: Register.GeneralSize,
3262 };
3263
3264 /// C6.2.165 LDPSW
3265 pub const Ldpsw = packed struct {
3266 Rt: Register.Encoded,
3267 Rn: Register.Encoded,
3268 Rt2: Register.Encoded,
3269 imm7: i7,
3270 L: L = .load,
3271 decoded23: u3 = 0b001,
3272 V: bool = false,
3273 decoded27: u3 = 0b101,
3274 opc: u2 = 0b01,
3275 };
3276
3277 pub const Decoded = union(enum) {
3278 unallocated,
3279 stp: Stp,
3280 ldp: Ldp,
3281 ldpsw: Ldpsw,
3282 };
3283 pub fn decode(inst: @This()) @This().Decoded {
3284 return switch (inst.group.opc) {
3285 0b00, 0b10 => switch (inst.group.L) {
3286 .store => .{ .stp = inst.stp },
3287 .load => .{ .ldp = inst.ldp },
3288 },
3289 0b01 => switch (inst.group.L) {
3290 else => .unallocated,
3291 .load => .{ .ldpsw = inst.ldpsw },
3292 },
3293 else => .unallocated,
3294 };
3295 }
3296 };
3297
3298 pub const Vector = packed union {
3299 group: @This().Group,
3300 stp: Stp,
3301 ldp: Ldp,
3302
3303 pub const Group = packed struct {
3304 Rt: Register.Encoded,
3305 Rn: Register.Encoded,
3306 Rt2: Register.Encoded,
3307 imm7: i7,
3308 L: L,
3309 decoded23: u3 = 0b001,
3310 V: bool = true,
3311 decoded27: u3 = 0b101,
3312 opc: VectorSize,
3313 };
3314
3315 /// C7.2.330 STP (SIMD&FP)
3316 pub const Stp = packed struct {
3317 Rt: Register.Encoded,
3318 Rn: Register.Encoded,
3319 Rt2: Register.Encoded,
3320 imm7: i7,
3321 L: L = .store,
3322 decoded23: u3 = 0b001,
3323 V: bool = true,
3324 decoded27: u3 = 0b101,
3325 opc: VectorSize,
3326 };
3327
3328 /// C7.2.190 LDP (SIMD&FP)
3329 pub const Ldp = packed struct {
3330 Rt: Register.Encoded,
3331 Rn: Register.Encoded,
3332 Rt2: Register.Encoded,
3333 imm7: i7,
3334 L: L = .load,
3335 decoded23: u3 = 0b001,
3336 V: bool = true,
3337 decoded27: u3 = 0b101,
3338 opc: VectorSize,
3339 };
3340
3341 pub const Decoded = union(enum) {
3342 unallocated,
3343 stp: Stp,
3344 ldp: Ldp,
3345 };
3346 pub fn decode(inst: @This()) @This().Decoded {
3347 return switch (inst.group.opc) {
3348 .single, .double, .quad => switch (inst.group.L) {
3349 .store => .{ .stp = inst.stp },
3350 .load => .{ .ldp = inst.ldp },
3351 },
3352 _ => .unallocated,
3353 };
3354 }
3355 };
3356
3357 pub const Decoded = union(enum) {
3358 integer: Integer,
3359 vector: Vector,
3360 };
3361 pub fn decode(inst: @This()) @This().Decoded {
3362 return switch (inst.group.V) {
3363 false => .{ .integer = inst.integer },
3364 true => .{ .vector = inst.vector },
3365 };
3366 }
3367 };
3368
3369 /// Load/store register pair (offset)
3370 pub const RegisterPairOffset = packed union {
3371 group: @This().Group,
3372 integer: Integer,
3373 vector: Vector,
3374
3375 pub const Group = packed struct {
3376 Rt: Register.Encoded,
3377 Rn: Register.Encoded,
3378 Rt2: Register.Encoded,
3379 imm7: i7,
3380 L: L,
3381 decoded23: u3 = 0b010,
3382 V: bool,
3383 decoded27: u3 = 0b101,
3384 opc: u2,
3385 };
3386
3387 pub const Integer = packed union {
3388 group: @This().Group,
3389 stp: Stp,
3390 ldp: Ldp,
3391 ldpsw: Ldpsw,
3392
3393 pub const Group = packed struct {
3394 Rt: Register.Encoded,
3395 Rn: Register.Encoded,
3396 Rt2: Register.Encoded,
3397 imm7: i7,
3398 L: L,
3399 decoded23: u3 = 0b010,
3400 V: bool = false,
3401 decoded27: u3 = 0b101,
3402 opc: u2,
3403 };
3404
3405 /// C6.2.321 STP
3406 pub const Stp = packed struct {
3407 Rt: Register.Encoded,
3408 Rn: Register.Encoded,
3409 Rt2: Register.Encoded,
3410 imm7: i7,
3411 L: L = .store,
3412 decoded23: u3 = 0b010,
3413 V: bool = false,
3414 decoded27: u3 = 0b101,
3415 opc0: u1 = 0b0,
3416 sf: Register.GeneralSize,
3417 };
3418
3419 /// C6.2.164 LDP
3420 pub const Ldp = packed struct {
3421 Rt: Register.Encoded,
3422 Rn: Register.Encoded,
3423 Rt2: Register.Encoded,
3424 imm7: i7,
3425 L: L = .load,
3426 decoded23: u3 = 0b010,
3427 V: bool = false,
3428 decoded27: u3 = 0b101,
3429 opc0: u1 = 0b0,
3430 sf: Register.GeneralSize,
3431 };
3432
3433 /// C6.2.165 LDPSW
3434 pub const Ldpsw = packed struct {
3435 Rt: Register.Encoded,
3436 Rn: Register.Encoded,
3437 Rt2: Register.Encoded,
3438 imm7: i7,
3439 L: L = .load,
3440 decoded23: u3 = 0b010,
3441 V: bool = false,
3442 decoded27: u3 = 0b101,
3443 opc: u2 = 0b01,
3444 };
3445
3446 pub const Decoded = union(enum) {
3447 unallocated,
3448 stp: Stp,
3449 ldp: Ldp,
3450 ldpsw: Ldpsw,
3451 };
3452 pub fn decode(inst: @This()) @This().Decoded {
3453 return switch (inst.group.opc) {
3454 0b00, 0b10 => switch (inst.group.L) {
3455 .store => .{ .stp = inst.stp },
3456 .load => .{ .ldp = inst.ldp },
3457 },
3458 0b01 => switch (inst.group.L) {
3459 else => .unallocated,
3460 .load => .{ .ldpsw = inst.ldpsw },
3461 },
3462 else => .unallocated,
3463 };
3464 }
3465 };
3466
3467 pub const Vector = packed union {
3468 group: @This().Group,
3469 stp: Stp,
3470 ldp: Ldp,
3471
3472 pub const Group = packed struct {
3473 Rt: Register.Encoded,
3474 Rn: Register.Encoded,
3475 Rt2: Register.Encoded,
3476 imm7: i7,
3477 L: L,
3478 decoded23: u3 = 0b010,
3479 V: bool = true,
3480 decoded27: u3 = 0b101,
3481 opc: VectorSize,
3482 };
3483
3484 /// C7.2.330 STP (SIMD&FP)
3485 pub const Stp = packed struct {
3486 Rt: Register.Encoded,
3487 Rn: Register.Encoded,
3488 Rt2: Register.Encoded,
3489 imm7: i7,
3490 L: L = .store,
3491 decoded23: u3 = 0b010,
3492 V: bool = true,
3493 decoded27: u3 = 0b101,
3494 opc: VectorSize,
3495 };
3496
3497 /// C7.2.190 LDP (SIMD&FP)
3498 pub const Ldp = packed struct {
3499 Rt: Register.Encoded,
3500 Rn: Register.Encoded,
3501 Rt2: Register.Encoded,
3502 imm7: i7,
3503 L: L = .load,
3504 decoded23: u3 = 0b010,
3505 V: bool = true,
3506 decoded27: u3 = 0b101,
3507 opc: VectorSize,
3508 };
3509
3510 pub const Decoded = union(enum) {
3511 unallocated,
3512 stp: Stp,
3513 ldp: Ldp,
3514 };
3515 pub fn decode(inst: @This()) @This().Decoded {
3516 return switch (inst.group.opc) {
3517 .single, .double, .quad => switch (inst.group.L) {
3518 .store => .{ .stp = inst.stp },
3519 .load => .{ .ldp = inst.ldp },
3520 },
3521 _ => .unallocated,
3522 };
3523 }
3524 };
3525
3526 pub const Decoded = union(enum) {
3527 integer: Integer,
3528 vector: Vector,
3529 };
3530 pub fn decode(inst: @This()) @This().Decoded {
3531 return switch (inst.group.V) {
3532 false => .{ .integer = inst.integer },
3533 true => .{ .vector = inst.vector },
3534 };
3535 }
3536 };
3537
3538 /// Load/store register pair (pre-indexed)
3539 pub const RegisterPairPreIndexed = packed union {
3540 group: @This().Group,
3541 integer: Integer,
3542 vector: Vector,
3543
3544 pub const Group = packed struct {
3545 Rt: Register.Encoded,
3546 Rn: Register.Encoded,
3547 Rt2: Register.Encoded,
3548 imm7: i7,
3549 L: L,
3550 decoded23: u3 = 0b011,
3551 V: bool,
3552 decoded27: u3 = 0b101,
3553 opc: u2,
3554 };
3555
3556 pub const Integer = packed union {
3557 group: @This().Group,
3558 stp: Stp,
3559 ldp: Ldp,
3560 ldpsw: Ldpsw,
3561
3562 pub const Group = packed struct {
3563 Rt: Register.Encoded,
3564 Rn: Register.Encoded,
3565 Rt2: Register.Encoded,
3566 imm7: i7,
3567 L: L,
3568 decoded23: u3 = 0b011,
3569 V: bool = false,
3570 decoded27: u3 = 0b101,
3571 opc: u2,
3572 };
3573
3574 /// C6.2.321 STP
3575 pub const Stp = packed struct {
3576 Rt: Register.Encoded,
3577 Rn: Register.Encoded,
3578 Rt2: Register.Encoded,
3579 imm7: i7,
3580 L: L = .store,
3581 decoded23: u3 = 0b011,
3582 V: bool = false,
3583 decoded27: u3 = 0b101,
3584 opc0: u1 = 0b0,
3585 sf: Register.GeneralSize,
3586 };
3587
3588 /// C6.2.164 LDP
3589 pub const Ldp = packed struct {
3590 Rt: Register.Encoded,
3591 Rn: Register.Encoded,
3592 Rt2: Register.Encoded,
3593 imm7: i7,
3594 L: L = .load,
3595 decoded23: u3 = 0b011,
3596 V: bool = false,
3597 decoded27: u3 = 0b101,
3598 opc0: u1 = 0b0,
3599 sf: Register.GeneralSize,
3600 };
3601
3602 /// C6.2.165 LDPSW
3603 pub const Ldpsw = packed struct {
3604 Rt: Register.Encoded,
3605 Rn: Register.Encoded,
3606 Rt2: Register.Encoded,
3607 imm7: i7,
3608 L: L = .load,
3609 decoded23: u3 = 0b011,
3610 V: bool = false,
3611 decoded27: u3 = 0b101,
3612 opc0: u2 = 0b01,
3613 };
3614
3615 pub const Decoded = union(enum) {
3616 unallocated,
3617 stp: Stp,
3618 ldp: Ldp,
3619 ldpsw: Ldpsw,
3620 };
3621 pub fn decode(inst: @This()) @This().Decoded {
3622 return switch (inst.group.opc) {
3623 0b00, 0b10 => switch (inst.group.L) {
3624 .store => .{ .stp = inst.stp },
3625 .load => .{ .ldp = inst.ldp },
3626 },
3627 0b01 => switch (inst.group.L) {
3628 else => .unallocated,
3629 .load => .{ .ldpsw = inst.ldpsw },
3630 },
3631 else => .unallocated,
3632 };
3633 }
3634 };
3635
3636 pub const Vector = packed union {
3637 group: @This().Group,
3638 stp: Stp,
3639 ldp: Ldp,
3640
3641 pub const Group = packed struct {
3642 Rt: Register.Encoded,
3643 Rn: Register.Encoded,
3644 Rt2: Register.Encoded,
3645 imm7: i7,
3646 L: L,
3647 decoded23: u3 = 0b011,
3648 V: bool = true,
3649 decoded27: u3 = 0b101,
3650 opc: VectorSize,
3651 };
3652
3653 /// C7.2.330 STP (SIMD&FP)
3654 pub const Stp = packed struct {
3655 Rt: Register.Encoded,
3656 Rn: Register.Encoded,
3657 Rt2: Register.Encoded,
3658 imm7: i7,
3659 L: L = .store,
3660 decoded23: u3 = 0b011,
3661 V: bool = true,
3662 decoded27: u3 = 0b101,
3663 opc: VectorSize,
3664 };
3665
3666 /// C7.2.190 LDP (SIMD&FP)
3667 pub const Ldp = packed struct {
3668 Rt: Register.Encoded,
3669 Rn: Register.Encoded,
3670 Rt2: Register.Encoded,
3671 imm7: i7,
3672 L: L = .load,
3673 decoded23: u3 = 0b011,
3674 V: bool = true,
3675 decoded27: u3 = 0b101,
3676 opc: VectorSize,
3677 };
3678
3679 pub const Decoded = union(enum) {
3680 unallocated,
3681 stp: Stp,
3682 ldp: Ldp,
3683 };
3684 pub fn decode(inst: @This()) @This().Decoded {
3685 return switch (inst.group.opc) {
3686 .single, .double, .quad => switch (inst.group.L) {
3687 .store => .{ .stp = inst.stp },
3688 .load => .{ .ldp = inst.ldp },
3689 },
3690 _ => .unallocated,
3691 };
3692 }
3693 };
3694
3695 pub const Decoded = union(enum) {
3696 integer: Integer,
3697 vector: Vector,
3698 };
3699 pub fn decode(inst: @This()) @This().Decoded {
3700 return switch (inst.group.V) {
3701 false => .{ .integer = inst.integer },
3702 true => .{ .vector = inst.vector },
3703 };
3704 }
3705 };
3706
3707 /// Load/store register (unscaled immediate)
3708 pub const RegisterUnscaledImmediate = packed union {
3709 group: @This().Group,
3710 integer: Integer,
3711 vector: Vector,
3712
3713 pub const Group = packed struct {
3714 Rt: Register.Encoded,
3715 Rn: Register.Encoded,
3716 decoded10: u2 = 0b00,
3717 imm9: i9,
3718 decoded21: u1 = 0b0,
3719 opc: u2,
3720 decoded24: u2 = 0b00,
3721 V: bool,
3722 decoded27: u3 = 0b111,
3723 size: u2,
3724 };
3725
3726 pub const Integer = packed union {
3727 group: @This().Group,
3728 sturb: Sturb,
3729 ldurb: Ldurb,
3730 ldursb: Ldursb,
3731 sturh: Sturh,
3732 ldurh: Ldurh,
3733 ldursh: Ldursh,
3734 stur: Stur,
3735 ldur: Ldur,
3736 ldursw: Ldursw,
3737 prfum: Prfum,
3738
3739 pub const Group = packed struct {
3740 Rt: Register.Encoded,
3741 Rn: Register.Encoded,
3742 decoded10: u2 = 0b00,
3743 imm9: i9,
3744 decoded21: u1 = 0b0,
3745 opc: u2,
3746 decoded24: u2 = 0b00,
3747 V: bool = false,
3748 decoded27: u3 = 0b111,
3749 size: Size,
3750 };
3751
3752 /// C6.2.347 STURB
3753 pub const Sturb = packed struct {
3754 Rt: Register.Encoded,
3755 Rn: Register.Encoded,
3756 decoded10: u2 = 0b00,
3757 imm9: i9,
3758 decoded21: u1 = 0b0,
3759 opc: u2 = 0b00,
3760 decoded24: u2 = 0b00,
3761 V: bool = false,
3762 decoded27: u3 = 0b111,
3763 size: Size = .byte,
3764 };
3765
3766 /// C6.2.203 LDURB
3767 pub const Ldurb = packed struct {
3768 Rt: Register.Encoded,
3769 Rn: Register.Encoded,
3770 decoded10: u2 = 0b00,
3771 imm9: i9,
3772 decoded21: u1 = 0b0,
3773 opc: u2 = 0b01,
3774 decoded24: u2 = 0b00,
3775 V: bool = false,
3776 decoded27: u3 = 0b111,
3777 size: Size = .byte,
3778 };
3779
3780 /// C6.2.205 LDURSB
3781 pub const Ldursb = packed struct {
3782 Rt: Register.Encoded,
3783 Rn: Register.Encoded,
3784 decoded10: u2 = 0b00,
3785 imm9: i9,
3786 decoded21: u1 = 0b0,
3787 opc0: u1,
3788 opc1: u1 = 0b1,
3789 decoded24: u2 = 0b00,
3790 V: bool = false,
3791 decoded27: u3 = 0b111,
3792 size: Size = .byte,
3793 };
3794
3795 /// C6.2.348 STURH
3796 pub const Sturh = packed struct {
3797 Rt: Register.Encoded,
3798 Rn: Register.Encoded,
3799 decoded10: u2 = 0b00,
3800 imm9: i9,
3801 decoded21: u1 = 0b0,
3802 opc: u2 = 0b00,
3803 decoded24: u2 = 0b00,
3804 V: bool = false,
3805 decoded27: u3 = 0b111,
3806 size: Size = .halfword,
3807 };
3808
3809 /// C6.2.204 LDURH
3810 pub const Ldurh = packed struct {
3811 Rt: Register.Encoded,
3812 Rn: Register.Encoded,
3813 decoded10: u2 = 0b00,
3814 imm9: i9,
3815 decoded21: u1 = 0b0,
3816 opc: u2 = 0b01,
3817 decoded24: u2 = 0b00,
3818 V: bool = false,
3819 decoded27: u3 = 0b111,
3820 size: Size = .halfword,
3821 };
3822
3823 /// C6.2.206 LDURSH
3824 pub const Ldursh = packed struct {
3825 Rt: Register.Encoded,
3826 Rn: Register.Encoded,
3827 decoded10: u2 = 0b00,
3828 imm9: i9,
3829 decoded21: u1 = 0b0,
3830 opc0: u1,
3831 opc1: u1 = 0b1,
3832 decoded24: u2 = 0b00,
3833 V: bool = false,
3834 decoded27: u3 = 0b111,
3835 size: Size = .halfword,
3836 };
3837
3838 /// C6.2.346 STUR
3839 pub const Stur = packed struct {
3840 Rt: Register.Encoded,
3841 Rn: Register.Encoded,
3842 decoded10: u2 = 0b00,
3843 imm9: i9,
3844 decoded21: u1 = 0b0,
3845 opc: u2 = 0b00,
3846 decoded24: u2 = 0b00,
3847 V: bool = false,
3848 decoded27: u3 = 0b111,
3849 sf: Register.GeneralSize,
3850 size1: u1 = 0b1,
3851 };
3852
3853 /// C6.2.202 LDUR
3854 pub const Ldur = packed struct {
3855 Rt: Register.Encoded,
3856 Rn: Register.Encoded,
3857 decoded10: u2 = 0b00,
3858 imm9: i9,
3859 decoded21: u1 = 0b0,
3860 opc: u2 = 0b01,
3861 decoded24: u2 = 0b00,
3862 V: bool = false,
3863 decoded27: u3 = 0b111,
3864 sf: Register.GeneralSize,
3865 size1: u1 = 0b1,
3866 };
3867
3868 /// C6.2.207 LDURSW
3869 pub const Ldursw = packed struct {
3870 Rt: Register.Encoded,
3871 Rn: Register.Encoded,
3872 decoded10: u2 = 0b00,
3873 imm9: i9,
3874 decoded21: u1 = 0b0,
3875 opc: u2 = 0b10,
3876 decoded24: u2 = 0b00,
3877 V: bool = false,
3878 decoded27: u3 = 0b111,
3879 size: Size = .word,
3880 };
3881
3882 /// C6.2.250 PRFUM
3883 pub const Prfum = packed struct {
3884 prfop: PrfOp,
3885 Rn: Register.Encoded,
3886 decoded10: u2 = 0b00,
3887 imm9: i9,
3888 decoded21: u1 = 0b0,
3889 opc: u2 = 0b10,
3890 decoded24: u2 = 0b00,
3891 V: bool = false,
3892 decoded27: u3 = 0b111,
3893 size: Size = .doubleword,
3894 };
3895
3896 pub const Decoded = union(enum) {
3897 unallocated,
3898 sturb: Sturb,
3899 ldurb: Ldurb,
3900 ldursb: Ldursb,
3901 sturh: Sturh,
3902 ldurh: Ldurh,
3903 ldursh: Ldursh,
3904 stur: Stur,
3905 ldur: Ldur,
3906 ldursw: Ldursw,
3907 prfum: Prfum,
3908 };
3909 pub fn decode(inst: @This()) @This().Decoded {
3910 return switch (inst.group.size) {
3911 .byte => switch (inst.group.V) {
3912 false => switch (inst.group.opc) {
3913 0b00 => .{ .sturb = inst.sturb },
3914 0b01 => .{ .ldurb = inst.ldurb },
3915 0b10, 0b11 => .{ .ldursb = inst.ldursb },
3916 },
3917 true => .unallocated,
3918 },
3919 .halfword => switch (inst.group.V) {
3920 false => switch (inst.group.opc) {
3921 0b00 => .{ .sturh = inst.sturh },
3922 0b01 => .{ .ldurh = inst.ldurh },
3923 0b10, 0b11 => .{ .ldursh = inst.ldursh },
3924 },
3925 true => .unallocated,
3926 },
3927 .word => switch (inst.group.V) {
3928 false => switch (inst.group.opc) {
3929 0b00 => .{ .stur = inst.stur },
3930 0b01 => .{ .ldur = inst.ldur },
3931 0b10 => .{ .ldursw = inst.ldursw },
3932 0b11 => .unallocated,
3933 },
3934 true => .unallocated,
3935 },
3936 .doubleword => switch (inst.group.V) {
3937 false => switch (inst.group.opc) {
3938 0b00 => .{ .stur = inst.stur },
3939 0b01 => .{ .ldur = inst.ldur },
3940 0b10 => .{ .prfum = inst.prfum },
3941 0b11 => .unallocated,
3942 },
3943 true => .unallocated,
3944 },
3945 };
3946 }
3947 };
3948
3949 pub const Vector = packed union {
3950 group: @This().Group,
3951 stur: Stur,
3952 ldur: Ldur,
3953
3954 pub const Group = packed struct {
3955 Rt: Register.Encoded,
3956 Rn: Register.Encoded,
3957 decoded10: u2 = 0b00,
3958 imm9: i9,
3959 decoded21: u1 = 0b0,
3960 opc0: L,
3961 opc1: Opc1,
3962 decoded24: u2 = 0b00,
3963 V: bool = true,
3964 decoded27: u3 = 0b111,
3965 size: Vector.Size,
3966 };
3967
3968 /// C7.2.333 STUR (SIMD&FP)
3969 pub const Stur = packed struct {
3970 Rt: Register.Encoded,
3971 Rn: Register.Encoded,
3972 decoded10: u2 = 0b00,
3973 imm9: i9,
3974 decoded21: u1 = 0b0,
3975 opc0: L = .store,
3976 opc1: Opc1,
3977 decoded24: u2 = 0b00,
3978 V: bool = true,
3979 decoded27: u3 = 0b111,
3980 size: Vector.Size,
3981 };
3982
3983 /// C7.2.194 LDUR (SIMD&FP)
3984 pub const Ldur = packed struct {
3985 Rt: Register.Encoded,
3986 Rn: Register.Encoded,
3987 decoded10: u2 = 0b00,
3988 imm9: i9,
3989 decoded21: u1 = 0b0,
3990 opc0: L = .load,
3991 opc1: Opc1,
3992 decoded24: u2 = 0b00,
3993 V: bool = true,
3994 decoded27: u3 = 0b111,
3995 size: Vector.Size,
3996 };
3997
3998 pub const Opc1 = packed struct {
3999 encoded: u1,
4000
4001 pub fn encode(ss: Register.ScalarSize) Opc1 {
4002 return .{ .encoded = switch (ss) {
4003 .byte, .half, .single, .double => 0b0,
4004 .quad => 0b1,
4005 } };
4006 }
4007
4008 pub fn decode(enc_opc1: Opc1, enc_size: Vector.Size) Register.ScalarSize {
4009 return switch (enc_size.encoded) {
4010 0b00 => switch (enc_opc1.encoded) {
4011 0b0 => .byte,
4012 0b1 => .quad,
4013 },
4014 0b01 => switch (enc_opc1.encoded) {
4015 0b0 => .half,
4016 0b1 => unreachable,
4017 },
4018 0b10 => switch (enc_opc1.encoded) {
4019 0b0 => .single,
4020 0b1 => unreachable,
4021 },
4022 0b11 => switch (enc_opc1.encoded) {
4023 0b0 => .double,
4024 0b1 => unreachable,
4025 },
4026 };
4027 }
4028 };
4029
4030 pub const Size = packed struct {
4031 encoded: u2,
4032
4033 pub fn encode(ss: Register.ScalarSize) Vector.Size {
4034 return .{ .encoded = switch (ss) {
4035 .byte, .quad => 0b00,
4036 .half => 0b01,
4037 .single => 0b10,
4038 .double => 0b11,
4039 } };
4040 }
4041 };
4042
4043 pub const Decoded = union(enum) {
4044 unallocated,
4045 stur: Stur,
4046 ldur: Ldur,
4047 };
4048 pub fn decode(inst: @This()) @This().Decoded {
4049 return switch (inst.group.size.encoded) {
4050 0b00 => switch (inst.group.opc0) {
4051 .store => .{ .stur = inst.stur },
4052 .load => .{ .ldur = inst.ldur },
4053 },
4054 0b01, 0b10, 0b11 => switch (inst.group.opc1.encoded) {
4055 0b0 => switch (inst.group.opc0) {
4056 .store => .{ .stur = inst.stur },
4057 .load => .{ .ldur = inst.ldur },
4058 },
4059 0b1 => .unallocated,
4060 },
4061 };
4062 }
4063 };
4064
4065 pub const Decoded = union(enum) {
4066 integer: Integer,
4067 vector: Vector,
4068 };
4069 pub fn decode(inst: @This()) @This().Decoded {
4070 return switch (inst.group.V) {
4071 false => .{ .integer = inst.integer },
4072 true => .{ .vector = inst.vector },
4073 };
4074 }
4075 };
4076
4077 /// Load/store register (immediate post-indexed)
4078 pub const RegisterImmediatePostIndexed = packed union {
4079 group: @This().Group,
4080 integer: Integer,
4081 vector: Vector,
4082
4083 pub const Group = packed struct {
4084 Rt: Register.Encoded,
4085 Rn: Register.Encoded,
4086 decoded10: u2 = 0b01,
4087 imm9: i9,
4088 decoded21: u1 = 0b0,
4089 opc: u2,
4090 decoded24: u2 = 0b00,
4091 V: bool,
4092 decoded27: u3 = 0b111,
4093 size: u2,
4094 };
4095
4096 pub const Integer = packed union {
4097 group: @This().Group,
4098 strb: Strb,
4099 ldrb: Ldrb,
4100 ldrsb: Ldrsb,
4101 strh: Strh,
4102 ldrh: Ldrh,
4103 ldrsh: Ldrsh,
4104 str: Str,
4105 ldr: Ldr,
4106 ldrsw: Ldrsw,
4107
4108 pub const Group = packed struct {
4109 Rt: Register.Encoded,
4110 Rn: Register.Encoded,
4111 decoded10: u2 = 0b01,
4112 imm9: i9,
4113 decoded21: u1 = 0b0,
4114 opc: u2,
4115 decoded24: u2 = 0b00,
4116 V: bool = false,
4117 decoded27: u3 = 0b111,
4118 size: Size,
4119 };
4120
4121 /// C6.2.324 STRB (immediate)
4122 pub const Strb = packed struct {
4123 Rt: Register.Encoded,
4124 Rn: Register.Encoded,
4125 decoded10: u2 = 0b01,
4126 imm9: i9,
4127 decoded21: u1 = 0b0,
4128 opc: u2 = 0b00,
4129 decoded24: u2 = 0b00,
4130 V: bool = false,
4131 decoded27: u3 = 0b111,
4132 size: Size = .byte,
4133 };
4134
4135 /// C6.2.170 LDRB (immediate)
4136 pub const Ldrb = packed struct {
4137 Rt: Register.Encoded,
4138 Rn: Register.Encoded,
4139 decoded10: u2 = 0b01,
4140 imm9: i9,
4141 decoded21: u1 = 0b0,
4142 opc: u2 = 0b01,
4143 decoded24: u2 = 0b00,
4144 V: bool = false,
4145 decoded27: u3 = 0b111,
4146 size: Size = .byte,
4147 };
4148
4149 /// C6.2.174 LDRSB (immediate)
4150 pub const Ldrsb = packed struct {
4151 Rt: Register.Encoded,
4152 Rn: Register.Encoded,
4153 decoded10: u2 = 0b01,
4154 imm9: i9,
4155 decoded21: u1 = 0b0,
4156 opc0: u1,
4157 opc1: u1 = 0b1,
4158 decoded24: u2 = 0b00,
4159 V: bool = false,
4160 decoded27: u3 = 0b111,
4161 size: Size = .byte,
4162 };
4163
4164 /// C6.2.326 STRH (immediate)
4165 pub const Strh = packed struct {
4166 Rt: Register.Encoded,
4167 Rn: Register.Encoded,
4168 decoded10: u2 = 0b01,
4169 imm9: i9,
4170 decoded21: u1 = 0b0,
4171 opc: u2 = 0b00,
4172 decoded24: u2 = 0b00,
4173 V: bool = false,
4174 decoded27: u3 = 0b111,
4175 size: Size = .halfword,
4176 };
4177
4178 /// C6.2.172 LDRH (immediate)
4179 pub const Ldrh = packed struct {
4180 Rt: Register.Encoded,
4181 Rn: Register.Encoded,
4182 decoded10: u2 = 0b01,
4183 imm9: i9,
4184 decoded21: u1 = 0b0,
4185 opc: u2 = 0b01,
4186 decoded24: u2 = 0b00,
4187 V: bool = false,
4188 decoded27: u3 = 0b111,
4189 size: Size = .halfword,
4190 };
4191
4192 /// C6.2.176 LDRSH (immediate)
4193 pub const Ldrsh = packed struct {
4194 Rt: Register.Encoded,
4195 Rn: Register.Encoded,
4196 decoded10: u2 = 0b01,
4197 imm9: i9,
4198 decoded21: u1 = 0b0,
4199 opc0: u1,
4200 opc1: u1 = 0b1,
4201 decoded24: u2 = 0b00,
4202 V: bool = false,
4203 decoded27: u3 = 0b111,
4204 size: Size = .halfword,
4205 };
4206
4207 /// C6.2.322 STR (immediate)
4208 pub const Str = packed struct {
4209 Rt: Register.Encoded,
4210 Rn: Register.Encoded,
4211 decoded10: u2 = 0b01,
4212 imm9: i9,
4213 decoded21: u1 = 0b0,
4214 opc: u2 = 0b00,
4215 decoded24: u2 = 0b00,
4216 V: bool = false,
4217 decoded27: u3 = 0b111,
4218 sf: Register.GeneralSize,
4219 size1: u1 = 0b1,
4220 };
4221
4222 /// C6.2.166 LDR (immediate)
4223 pub const Ldr = packed struct {
4224 Rt: Register.Encoded,
4225 Rn: Register.Encoded,
4226 decoded10: u2 = 0b01,
4227 imm9: i9,
4228 decoded21: u1 = 0b0,
4229 opc: u2 = 0b01,
4230 decoded24: u2 = 0b00,
4231 V: bool = false,
4232 decoded27: u3 = 0b111,
4233 sf: Register.GeneralSize,
4234 size1: u1 = 0b1,
4235 };
4236
4237 /// C6.2.178 LDRSW (immediate)
4238 pub const Ldrsw = packed struct {
4239 Rt: Register.Encoded,
4240 Rn: Register.Encoded,
4241 decoded10: u2 = 0b01,
4242 imm9: i9,
4243 decoded21: u1 = 0b0,
4244 opc: u2 = 0b10,
4245 decoded24: u2 = 0b00,
4246 V: bool = false,
4247 decoded27: u3 = 0b111,
4248 size: Size = .word,
4249 };
4250
4251 pub const Decoded = union(enum) {
4252 unallocated,
4253 strb: Strb,
4254 ldrb: Ldrb,
4255 ldrsb: Ldrsb,
4256 strh: Strh,
4257 ldrh: Ldrh,
4258 ldrsh: Ldrsh,
4259 str: Str,
4260 ldr: Ldr,
4261 ldrsw: Ldrsw,
4262 };
4263 pub fn decode(inst: @This()) @This().Decoded {
4264 return switch (inst.group.size) {
4265 .byte => switch (inst.group.V) {
4266 false => switch (inst.group.opc) {
4267 0b00 => .{ .strb = inst.strb },
4268 0b01 => .{ .ldrb = inst.ldrb },
4269 0b10, 0b11 => .{ .ldrsb = inst.ldrsb },
4270 },
4271 true => .unallocated,
4272 },
4273 .halfword => switch (inst.group.V) {
4274 false => switch (inst.group.opc) {
4275 0b00 => .{ .strh = inst.strh },
4276 0b01 => .{ .ldrh = inst.ldrh },
4277 0b10, 0b11 => .{ .ldrsh = inst.ldrsh },
4278 },
4279 true => .unallocated,
4280 },
4281 .word => switch (inst.group.V) {
4282 false => switch (inst.group.opc) {
4283 0b00 => .{ .str = inst.str },
4284 0b01 => .{ .ldr = inst.ldr },
4285 0b10 => .{ .ldrsw = inst.ldrsw },
4286 0b11 => .unallocated,
4287 },
4288 true => .unallocated,
4289 },
4290 .doubleword => switch (inst.group.V) {
4291 false => switch (inst.group.opc) {
4292 0b00 => .{ .str = inst.str },
4293 0b01 => .{ .ldr = inst.ldr },
4294 0b10, 0b11 => .unallocated,
4295 },
4296 true => .unallocated,
4297 },
4298 };
4299 }
4300 };
4301
4302 pub const Vector = packed union {
4303 group: @This().Group,
4304 str: Str,
4305 ldr: Ldr,
4306
4307 pub const Group = packed struct {
4308 Rt: Register.Encoded,
4309 Rn: Register.Encoded,
4310 decoded10: u2 = 0b01,
4311 imm9: i9,
4312 decoded21: u1 = 0b0,
4313 opc0: L,
4314 opc1: Opc1,
4315 decoded24: u2 = 0b00,
4316 V: bool = true,
4317 decoded27: u3 = 0b111,
4318 size: Vector.Size,
4319 };
4320
4321 /// C7.2.331 STR (immediate, SIMD&FP)
4322 pub const Str = packed struct {
4323 Rt: Register.Encoded,
4324 Rn: Register.Encoded,
4325 decoded10: u2 = 0b01,
4326 imm9: i9,
4327 decoded21: u1 = 0b0,
4328 opc0: L = .store,
4329 opc1: Opc1,
4330 decoded24: u2 = 0b00,
4331 V: bool = true,
4332 decoded27: u3 = 0b111,
4333 size: Vector.Size,
4334 };
4335
4336 /// C7.2.191 LDR (immediate, SIMD&FP)
4337 pub const Ldr = packed struct {
4338 Rt: Register.Encoded,
4339 Rn: Register.Encoded,
4340 decoded10: u2 = 0b01,
4341 imm9: i9,
4342 decoded21: u1 = 0b0,
4343 opc0: L = .load,
4344 opc1: Opc1,
4345 decoded24: u2 = 0b00,
4346 V: bool = true,
4347 decoded27: u3 = 0b111,
4348 size: Vector.Size,
4349 };
4350
4351 pub const Opc1 = packed struct {
4352 encoded: u1,
4353
4354 pub fn encode(ss: Register.ScalarSize) Opc1 {
4355 return .{ .encoded = switch (ss) {
4356 .byte, .half, .single, .double => 0b0,
4357 .quad => 0b1,
4358 } };
4359 }
4360
4361 pub fn decode(enc_opc1: Opc1, enc_size: Vector.Size) Register.ScalarSize {
4362 return switch (enc_size.encoded) {
4363 0b00 => switch (enc_opc1.encoded) {
4364 0b0 => .byte,
4365 0b1 => .quad,
4366 },
4367 0b01 => switch (enc_opc1.encoded) {
4368 0b0 => .half,
4369 0b1 => unreachable,
4370 },
4371 0b10 => switch (enc_opc1.encoded) {
4372 0b0 => .single,
4373 0b1 => unreachable,
4374 },
4375 0b11 => switch (enc_opc1.encoded) {
4376 0b0 => .double,
4377 0b1 => unreachable,
4378 },
4379 };
4380 }
4381 };
4382
4383 pub const Size = packed struct {
4384 encoded: u2,
4385
4386 pub fn encode(ss: Register.ScalarSize) Vector.Size {
4387 return .{ .encoded = switch (ss) {
4388 .byte, .quad => 0b00,
4389 .half => 0b01,
4390 .single => 0b10,
4391 .double => 0b11,
4392 } };
4393 }
4394 };
4395
4396 pub const Decoded = union(enum) {
4397 unallocated,
4398 str: Str,
4399 ldr: Ldr,
4400 };
4401 pub fn decode(inst: @This()) @This().Decoded {
4402 return switch (inst.group.size.encoded) {
4403 0b00 => switch (inst.group.opc0) {
4404 .store => .{ .str = inst.str },
4405 .load => .{ .ldr = inst.ldr },
4406 },
4407 0b01, 0b10, 0b11 => switch (inst.group.opc1.encoded) {
4408 0b0 => switch (inst.group.opc0) {
4409 .store => .{ .str = inst.str },
4410 .load => .{ .ldr = inst.ldr },
4411 },
4412 0b1 => .unallocated,
4413 },
4414 };
4415 }
4416 };
4417
4418 pub const Decoded = union(enum) {
4419 integer: Integer,
4420 vector: Vector,
4421 };
4422 pub fn decode(inst: @This()) @This().Decoded {
4423 return switch (inst.group.V) {
4424 false => .{ .integer = inst.integer },
4425 true => .{ .vector = inst.vector },
4426 };
4427 }
4428 };
4429
4430 /// Load/store register (unprivileged)
4431 pub const RegisterUnprivileged = packed struct {
4432 Rt: Register.Encoded,
4433 Rn: Register.Encoded,
4434 decoded10: u2 = 0b10,
4435 imm9: i9,
4436 decoded21: u1 = 0b0,
4437 opc: u2,
4438 decoded24: u2 = 0b00,
4439 V: bool,
4440 decoded27: u3 = 0b111,
4441 size: Size,
4442 };
4443
4444 /// Load/store register (immediate pre-indexed)
4445 pub const RegisterImmediatePreIndexed = packed union {
4446 group: @This().Group,
4447 integer: Integer,
4448 vector: Vector,
4449
4450 pub const Group = packed struct {
4451 Rt: Register.Encoded,
4452 Rn: Register.Encoded,
4453 decoded10: u2 = 0b11,
4454 imm9: i9,
4455 decoded21: u1 = 0b0,
4456 opc: u2,
4457 decoded24: u2 = 0b00,
4458 V: bool,
4459 decoded27: u3 = 0b111,
4460 size: u2,
4461 };
4462
4463 pub const Integer = packed union {
4464 group: @This().Group,
4465 strb: Strb,
4466 ldrb: Ldrb,
4467 ldrsb: Ldrsb,
4468 strh: Strh,
4469 ldrh: Ldrh,
4470 ldrsh: Ldrsh,
4471 str: Str,
4472 ldr: Ldr,
4473 ldrsw: Ldrsw,
4474
4475 pub const Group = packed struct {
4476 Rt: Register.Encoded,
4477 Rn: Register.Encoded,
4478 decoded10: u2 = 0b11,
4479 imm9: i9,
4480 decoded21: u1 = 0b0,
4481 opc: u2,
4482 decoded24: u2 = 0b00,
4483 V: bool = false,
4484 decoded27: u3 = 0b111,
4485 size: Size,
4486 };
4487
4488 /// C6.2.324 STRB (immediate)
4489 pub const Strb = packed struct {
4490 Rt: Register.Encoded,
4491 Rn: Register.Encoded,
4492 decoded10: u2 = 0b11,
4493 imm9: i9,
4494 decoded21: u1 = 0b0,
4495 opc: u2 = 0b00,
4496 decoded24: u2 = 0b00,
4497 V: bool = false,
4498 decoded27: u3 = 0b111,
4499 size: Size = .byte,
4500 };
4501
4502 /// C6.2.170 LDRB (immediate)
4503 pub const Ldrb = packed struct {
4504 Rt: Register.Encoded,
4505 Rn: Register.Encoded,
4506 decoded10: u2 = 0b11,
4507 imm9: i9,
4508 decoded21: u1 = 0b0,
4509 opc: u2 = 0b01,
4510 decoded24: u2 = 0b00,
4511 V: bool = false,
4512 decoded27: u3 = 0b111,
4513 size: Size = .byte,
4514 };
4515
4516 /// C6.2.174 LDRSB (immediate)
4517 pub const Ldrsb = packed struct {
4518 Rt: Register.Encoded,
4519 Rn: Register.Encoded,
4520 decoded10: u2 = 0b11,
4521 imm9: i9,
4522 decoded21: u1 = 0b0,
4523 opc0: u1,
4524 opc1: u1 = 0b1,
4525 decoded24: u2 = 0b00,
4526 V: bool = false,
4527 decoded27: u3 = 0b111,
4528 size: Size = .byte,
4529 };
4530
4531 /// C6.2.326 STRH (immediate)
4532 pub const Strh = packed struct {
4533 Rt: Register.Encoded,
4534 Rn: Register.Encoded,
4535 decoded10: u2 = 0b11,
4536 imm9: i9,
4537 decoded21: u1 = 0b0,
4538 opc: u2 = 0b00,
4539 decoded24: u2 = 0b00,
4540 V: bool = false,
4541 decoded27: u3 = 0b111,
4542 size: Size = .halfword,
4543 };
4544
4545 /// C6.2.172 LDRH (immediate)
4546 pub const Ldrh = packed struct {
4547 Rt: Register.Encoded,
4548 Rn: Register.Encoded,
4549 decoded10: u2 = 0b11,
4550 imm9: i9,
4551 decoded21: u1 = 0b0,
4552 opc: u2 = 0b01,
4553 decoded24: u2 = 0b00,
4554 V: bool = false,
4555 decoded27: u3 = 0b111,
4556 size: Size = .halfword,
4557 };
4558
4559 /// C6.2.176 LDRSH (immediate)
4560 pub const Ldrsh = packed struct {
4561 Rt: Register.Encoded,
4562 Rn: Register.Encoded,
4563 decoded10: u2 = 0b11,
4564 imm9: i9,
4565 decoded21: u1 = 0b0,
4566 opc0: u1,
4567 opc1: u1 = 0b1,
4568 decoded24: u2 = 0b00,
4569 V: bool = false,
4570 decoded27: u3 = 0b111,
4571 size: Size = .halfword,
4572 };
4573
4574 /// C6.2.322 STR (immediate)
4575 pub const Str = packed struct {
4576 Rt: Register.Encoded,
4577 Rn: Register.Encoded,
4578 decoded10: u2 = 0b11,
4579 imm9: i9,
4580 decoded21: u1 = 0b0,
4581 opc: u2 = 0b00,
4582 decoded24: u2 = 0b00,
4583 V: bool = false,
4584 decoded27: u3 = 0b111,
4585 sf: Register.GeneralSize,
4586 size1: u1 = 0b1,
4587 };
4588
4589 /// C6.2.166 LDR (immediate)
4590 pub const Ldr = packed struct {
4591 Rt: Register.Encoded,
4592 Rn: Register.Encoded,
4593 decoded10: u2 = 0b11,
4594 imm9: i9,
4595 decoded21: u1 = 0b0,
4596 opc: u2 = 0b01,
4597 decoded24: u2 = 0b00,
4598 V: bool = false,
4599 decoded27: u3 = 0b111,
4600 sf: Register.GeneralSize,
4601 size1: u1 = 0b1,
4602 };
4603
4604 /// C6.2.178 LDRSW (immediate)
4605 pub const Ldrsw = packed struct {
4606 Rt: Register.Encoded,
4607 Rn: Register.Encoded,
4608 decoded10: u2 = 0b11,
4609 imm9: i9,
4610 decoded21: u1 = 0b0,
4611 opc: u2 = 0b10,
4612 decoded24: u2 = 0b00,
4613 V: bool = false,
4614 decoded27: u3 = 0b111,
4615 size: Size = .word,
4616 };
4617
4618 pub const Decoded = union(enum) {
4619 unallocated,
4620 strb: Strb,
4621 ldrb: Ldrb,
4622 ldrsb: Ldrsb,
4623 strh: Strh,
4624 ldrh: Ldrh,
4625 ldrsh: Ldrsh,
4626 str: Str,
4627 ldr: Ldr,
4628 ldrsw: Ldrsw,
4629 };
4630 pub fn decode(inst: @This()) @This().Decoded {
4631 return switch (inst.group.size) {
4632 .byte => switch (inst.group.opc) {
4633 0b00 => .{ .strb = inst.strb },
4634 0b01 => .{ .ldrb = inst.ldrb },
4635 0b10, 0b11 => .{ .ldrsb = inst.ldrsb },
4636 },
4637 .halfword => switch (inst.group.opc) {
4638 0b00 => .{ .strh = inst.strh },
4639 0b01 => .{ .ldrh = inst.ldrh },
4640 0b10, 0b11 => .{ .ldrsh = inst.ldrsh },
4641 },
4642 .word => switch (inst.group.opc) {
4643 0b00 => .{ .str = inst.str },
4644 0b01 => .{ .ldr = inst.ldr },
4645 0b10 => .{ .ldrsw = inst.ldrsw },
4646 0b11 => .unallocated,
4647 },
4648 .doubleword => switch (inst.group.opc) {
4649 0b00 => .{ .str = inst.str },
4650 0b01 => .{ .ldr = inst.ldr },
4651 0b10, 0b11 => .unallocated,
4652 },
4653 };
4654 }
4655 };
4656
4657 pub const Vector = packed union {
4658 group: @This().Group,
4659 str: Str,
4660 ldr: Ldr,
4661
4662 pub const Group = packed struct {
4663 Rt: Register.Encoded,
4664 Rn: Register.Encoded,
4665 decoded10: u2 = 0b11,
4666 imm9: i9,
4667 decoded21: u1 = 0b0,
4668 opc0: L,
4669 opc1: Opc1,
4670 decoded24: u2 = 0b00,
4671 V: bool = true,
4672 decoded27: u3 = 0b111,
4673 size: Vector.Size,
4674 };
4675
4676 /// C7.2.331 STR (immediate, SIMD&FP)
4677 pub const Str = packed struct {
4678 Rt: Register.Encoded,
4679 Rn: Register.Encoded,
4680 decoded10: u2 = 0b11,
4681 imm9: i9,
4682 decoded21: u1 = 0b0,
4683 opc0: L = .store,
4684 opc1: Opc1,
4685 decoded24: u2 = 0b00,
4686 V: bool = true,
4687 decoded27: u3 = 0b111,
4688 size: Vector.Size,
4689 };
4690
4691 /// C7.2.191 LDR (immediate, SIMD&FP)
4692 pub const Ldr = packed struct {
4693 Rt: Register.Encoded,
4694 Rn: Register.Encoded,
4695 decoded10: u2 = 0b11,
4696 imm9: i9,
4697 decoded21: u1 = 0b0,
4698 opc0: L = .load,
4699 opc1: Opc1,
4700 decoded24: u2 = 0b00,
4701 V: bool = true,
4702 decoded27: u3 = 0b111,
4703 size: Vector.Size,
4704 };
4705
4706 pub const Opc1 = packed struct {
4707 encoded: u1,
4708
4709 pub fn encode(ss: Register.ScalarSize) Opc1 {
4710 return .{ .encoded = switch (ss) {
4711 .byte, .half, .single, .double => 0b0,
4712 .quad => 0b1,
4713 } };
4714 }
4715
4716 pub fn decode(enc_opc1: Opc1, enc_size: Vector.Size) Register.ScalarSize {
4717 return switch (enc_size.encoded) {
4718 0b00 => switch (enc_opc1.encoded) {
4719 0b0 => .byte,
4720 0b1 => .quad,
4721 },
4722 0b01 => switch (enc_opc1.encoded) {
4723 0b0 => .half,
4724 0b1 => unreachable,
4725 },
4726 0b10 => switch (enc_opc1.encoded) {
4727 0b0 => .single,
4728 0b1 => unreachable,
4729 },
4730 0b11 => switch (enc_opc1.encoded) {
4731 0b0 => .double,
4732 0b1 => unreachable,
4733 },
4734 };
4735 }
4736 };
4737
4738 pub const Size = packed struct {
4739 encoded: u2,
4740
4741 pub fn encode(ss: Register.ScalarSize) Vector.Size {
4742 return .{ .encoded = switch (ss) {
4743 .byte, .quad => 0b00,
4744 .half => 0b01,
4745 .single => 0b10,
4746 .double => 0b11,
4747 } };
4748 }
4749 };
4750
4751 pub const Decoded = union(enum) {
4752 unallocated,
4753 str: Str,
4754 ldr: Ldr,
4755 };
4756 pub fn decode(inst: @This()) @This().Decoded {
4757 return switch (inst.group.size.encoded) {
4758 0b00 => switch (inst.group.opc0) {
4759 .store => .{ .str = inst.str },
4760 .load => .{ .ldr = inst.ldr },
4761 },
4762 0b01, 0b10, 0b11 => switch (inst.group.opc1.encoded) {
4763 0b0 => switch (inst.group.opc0) {
4764 .store => .{ .str = inst.str },
4765 .load => .{ .ldr = inst.ldr },
4766 },
4767 0b1 => .unallocated,
4768 },
4769 };
4770 }
4771 };
4772
4773 pub const Decoded = union(enum) {
4774 integer: Integer,
4775 vector: Vector,
4776 };
4777 pub fn decode(inst: @This()) @This().Decoded {
4778 return switch (inst.group.V) {
4779 false => .{ .integer = inst.integer },
4780 true => .{ .vector = inst.vector },
4781 };
4782 }
4783 };
4784
4785 /// Load/store register (register offset)
4786 pub const RegisterRegisterOffset = packed union {
4787 group: @This().Group,
4788 integer: Integer,
4789 vector: Vector,
4790
4791 pub const Group = packed struct {
4792 Rt: Register.Encoded,
4793 Rn: Register.Encoded,
4794 decoded10: u2 = 0b10,
4795 S: bool,
4796 option: Option,
4797 Rm: Register.Encoded,
4798 decoded21: u1 = 0b1,
4799 opc: u2,
4800 decoded24: u2 = 0b00,
4801 V: bool,
4802 decoded27: u3 = 0b111,
4803 size: u2,
4804 };
4805
4806 pub const Integer = packed union {
4807 group: @This().Group,
4808 strb: Strb,
4809 ldrb: Ldrb,
4810 ldrsb: Ldrsb,
4811 strh: Strh,
4812 ldrh: Ldrh,
4813 ldrsh: Ldrsh,
4814 str: Str,
4815 ldr: Ldr,
4816 ldrsw: Ldrsw,
4817 prfm: Prfm,
4818
4819 pub const Group = packed struct {
4820 Rt: Register.Encoded,
4821 Rn: Register.Encoded,
4822 decoded10: u2 = 0b10,
4823 S: bool,
4824 option: Option,
4825 Rm: Register.Encoded,
4826 decoded21: u1 = 0b1,
4827 opc: u2,
4828 decoded24: u2 = 0b00,
4829 V: bool = false,
4830 decoded27: u3 = 0b111,
4831 size: Size,
4832 };
4833
4834 /// C6.2.325 STRB (register)
4835 pub const Strb = packed struct {
4836 Rt: Register.Encoded,
4837 Rn: Register.Encoded,
4838 decoded10: u2 = 0b10,
4839 S: bool,
4840 option: Option,
4841 Rm: Register.Encoded,
4842 decoded21: u1 = 0b1,
4843 opc: u2 = 0b00,
4844 decoded24: u2 = 0b00,
4845 V: bool = false,
4846 decoded27: u3 = 0b111,
4847 size: Size = .byte,
4848 };
4849
4850 /// C6.2.171 LDRB (register)
4851 pub const Ldrb = packed struct {
4852 Rt: Register.Encoded,
4853 Rn: Register.Encoded,
4854 decoded10: u2 = 0b10,
4855 S: bool,
4856 option: Option,
4857 Rm: Register.Encoded,
4858 decoded21: u1 = 0b1,
4859 opc: u2 = 0b01,
4860 decoded24: u2 = 0b00,
4861 V: bool = false,
4862 decoded27: u3 = 0b111,
4863 size: Size = .byte,
4864 };
4865
4866 /// C6.2.175 LDRSB (register)
4867 pub const Ldrsb = packed struct {
4868 Rt: Register.Encoded,
4869 Rn: Register.Encoded,
4870 decoded10: u2 = 0b10,
4871 S: bool,
4872 option: Option,
4873 Rm: Register.Encoded,
4874 decoded21: u1 = 0b1,
4875 opc0: u1,
4876 opc1: u1 = 0b1,
4877 decoded24: u2 = 0b00,
4878 V: bool = false,
4879 decoded27: u3 = 0b111,
4880 size: Size = .byte,
4881 };
4882
4883 /// C6.2.327 STRH (register)
4884 pub const Strh = packed struct {
4885 Rt: Register.Encoded,
4886 Rn: Register.Encoded,
4887 decoded10: u2 = 0b10,
4888 S: bool,
4889 option: Option,
4890 Rm: Register.Encoded,
4891 decoded21: u1 = 0b1,
4892 opc: u2 = 0b00,
4893 decoded24: u2 = 0b00,
4894 V: bool = false,
4895 decoded27: u3 = 0b111,
4896 size: Size = .halfword,
4897 };
4898
4899 /// C6.2.173 LDRH (register)
4900 pub const Ldrh = packed struct {
4901 Rt: Register.Encoded,
4902 Rn: Register.Encoded,
4903 decoded10: u2 = 0b10,
4904 S: bool,
4905 option: Option,
4906 Rm: Register.Encoded,
4907 decoded21: u1 = 0b1,
4908 opc: u2 = 0b01,
4909 decoded24: u2 = 0b00,
4910 V: bool = false,
4911 decoded27: u3 = 0b111,
4912 size: Size = .halfword,
4913 };
4914
4915 /// C6.2.177 LDRSH (register)
4916 pub const Ldrsh = packed struct {
4917 Rt: Register.Encoded,
4918 Rn: Register.Encoded,
4919 decoded10: u2 = 0b10,
4920 S: bool,
4921 option: Option,
4922 Rm: Register.Encoded,
4923 decoded21: u1 = 0b1,
4924 opc0: u1,
4925 opc1: u1 = 0b1,
4926 decoded24: u2 = 0b00,
4927 V: bool = false,
4928 decoded27: u3 = 0b111,
4929 size: Size = .halfword,
4930 };
4931
4932 /// C6.2.323 STR (register)
4933 pub const Str = packed struct {
4934 Rt: Register.Encoded,
4935 Rn: Register.Encoded,
4936 decoded10: u2 = 0b10,
4937 S: bool,
4938 option: Option,
4939 Rm: Register.Encoded,
4940 decoded21: u1 = 0b1,
4941 opc: u2 = 0b00,
4942 decoded24: u2 = 0b00,
4943 V: bool = false,
4944 decoded27: u3 = 0b111,
4945 sf: Register.GeneralSize,
4946 size1: u1 = 0b1,
4947 };
4948
4949 /// C6.2.168 LDR (register)
4950 pub const Ldr = packed struct {
4951 Rt: Register.Encoded,
4952 Rn: Register.Encoded,
4953 decoded10: u2 = 0b10,
4954 S: bool,
4955 option: Option,
4956 Rm: Register.Encoded,
4957 decoded21: u1 = 0b1,
4958 opc: u2 = 0b01,
4959 decoded24: u2 = 0b00,
4960 V: bool = false,
4961 decoded27: u3 = 0b111,
4962 sf: Register.GeneralSize,
4963 size1: u1 = 0b1,
4964 };
4965
4966 /// C6.2.180 LDRSW (register)
4967 pub const Ldrsw = packed struct {
4968 Rt: Register.Encoded,
4969 Rn: Register.Encoded,
4970 decoded10: u2 = 0b10,
4971 S: bool,
4972 option: Option,
4973 Rm: Register.Encoded,
4974 decoded21: u1 = 0b1,
4975 opc: u2 = 0b10,
4976 decoded24: u2 = 0b00,
4977 V: bool = false,
4978 decoded27: u3 = 0b111,
4979 size: Size = .word,
4980 };
4981
4982 /// C6.2.249 PRFM (register)
4983 pub const Prfm = packed struct {
4984 prfop: PrfOp,
4985 Rn: Register.Encoded,
4986 decoded10: u2 = 0b10,
4987 S: bool,
4988 option: Option,
4989 Rm: Register.Encoded,
4990 decoded21: u1 = 0b1,
4991 opc: u2 = 0b10,
4992 decoded24: u2 = 0b00,
4993 V: bool = false,
4994 decoded27: u3 = 0b111,
4995 size: Size = .doubleword,
4996 };
4997
4998 pub const Decoded = union(enum) {
4999 unallocated,
5000 strb: Strb,
5001 ldrb: Ldrb,
5002 ldrsb: Ldrsb,
5003 strh: Strh,
5004 ldrh: Ldrh,
5005 ldrsh: Ldrsh,
5006 str: Str,
5007 ldr: Ldr,
5008 ldrsw: Ldrsw,
5009 prfm: Prfm,
5010 };
5011 pub fn decode(inst: @This()) @This().Decoded {
5012 return switch (inst.group.size) {
5013 .byte => switch (inst.group.V) {
5014 false => switch (inst.group.opc) {
5015 0b00 => .{ .strb = inst.strb },
5016 0b01 => .{ .ldrb = inst.ldrb },
5017 0b10, 0b11 => .{ .ldrsb = inst.ldrsb },
5018 },
5019 true => .unallocated,
5020 },
5021 .halfword => switch (inst.group.V) {
5022 false => switch (inst.group.opc) {
5023 0b00 => .{ .strh = inst.strh },
5024 0b01 => .{ .ldrh = inst.ldrh },
5025 0b10, 0b11 => .{ .ldrsh = inst.ldrsh },
5026 },
5027 true => .unallocated,
5028 },
5029 .word => switch (inst.group.V) {
5030 false => switch (inst.group.opc) {
5031 0b00 => .{ .str = inst.str },
5032 0b01 => .{ .ldr = inst.ldr },
5033 0b10 => .{ .ldrsw = inst.ldrsw },
5034 0b11 => .unallocated,
5035 },
5036 true => .unallocated,
5037 },
5038 .doubleword => switch (inst.group.V) {
5039 false => switch (inst.group.opc) {
5040 0b00 => .{ .str = inst.str },
5041 0b01 => .{ .ldr = inst.ldr },
5042 0b10 => .{ .prfm = inst.prfm },
5043 0b11 => .unallocated,
5044 },
5045 true => .unallocated,
5046 },
5047 };
5048 }
5049 };
5050
5051 pub const Vector = packed union {
5052 group: @This().Group,
5053 str: Str,
5054 ldr: Ldr,
5055
5056 pub const Group = packed struct {
5057 Rt: Register.Encoded,
5058 Rn: Register.Encoded,
5059 decoded10: u2 = 0b10,
5060 S: bool,
5061 option: Option,
5062 Rm: Register.Encoded,
5063 decoded21: u1 = 0b1,
5064 opc: u2,
5065 decoded24: u2 = 0b00,
5066 V: bool = true,
5067 decoded27: u3 = 0b111,
5068 size: Vector.Size,
5069 };
5070
5071 /// C7.2.332 STR (register, SIMD&FP)
5072 pub const Str = packed struct {
5073 Rt: Register.Encoded,
5074 Rn: Register.Encoded,
5075 decoded10: u2 = 0b10,
5076 S: bool,
5077 option: Option,
5078 Rm: Register.Encoded,
5079 decoded21: u1 = 0b1,
5080 opc0: L = .store,
5081 opc1: Opc1,
5082 decoded24: u2 = 0b00,
5083 V: bool = true,
5084 decoded27: u3 = 0b111,
5085 size: Vector.Size,
5086 };
5087
5088 /// C7.2.193 LDR (register, SIMD&FP)
5089 pub const Ldr = packed struct {
5090 Rt: Register.Encoded,
5091 Rn: Register.Encoded,
5092 decoded10: u2 = 0b10,
5093 S: bool,
5094 option: Option,
5095 Rm: Register.Encoded,
5096 decoded21: u1 = 0b1,
5097 opc0: L = .load,
5098 opc1: Opc1,
5099 decoded24: u2 = 0b00,
5100 V: bool = true,
5101 decoded27: u3 = 0b111,
5102 size: Vector.Size,
5103 };
5104
5105 pub const Opc1 = packed struct {
5106 encoded: u1,
5107
5108 pub fn encode(ss: Register.ScalarSize) Opc1 {
5109 return .{ .encoded = switch (ss) {
5110 .byte, .half, .single, .double => 0b0,
5111 .quad => 0b1,
5112 } };
5113 }
5114
5115 pub fn decode(enc_opc1: Opc1, enc_size: Vector.Size) Register.ScalarSize {
5116 return switch (enc_size.encoded) {
5117 0b00 => switch (enc_opc1.encoded) {
5118 0b0 => .byte,
5119 0b1 => .quad,
5120 },
5121 0b01 => switch (enc_opc1.encoded) {
5122 0b0 => .half,
5123 0b1 => unreachable,
5124 },
5125 0b10 => switch (enc_opc1.encoded) {
5126 0b0 => .single,
5127 0b1 => unreachable,
5128 },
5129 0b11 => switch (enc_opc1.encoded) {
5130 0b0 => .double,
5131 0b1 => unreachable,
5132 },
5133 };
5134 }
5135 };
5136
5137 pub const Size = packed struct {
5138 encoded: u2,
5139
5140 pub fn encode(ss: Register.ScalarSize) Vector.Size {
5141 return .{ .encoded = switch (ss) {
5142 .byte, .quad => 0b00,
5143 .half => 0b01,
5144 .single => 0b10,
5145 .double => 0b11,
5146 } };
5147 }
5148 };
5149 };
5150
5151 pub const Option = enum(u3) {
5152 uxtw = 0b010,
5153 lsl = 0b011,
5154 sxtw = 0b110,
5155 sxtx = 0b111,
5156 _,
5157
5158 pub fn sf(option: Option) Register.GeneralSize {
5159 return switch (option) {
5160 .uxtw, .sxtw => .word,
5161 .lsl, .sxtx => .doubleword,
5162 _ => unreachable,
5163 };
5164 }
5165 };
5166
5167 pub const Extend = union(Option) {
5168 uxtw: Amount,
5169 lsl: Amount,
5170 sxtw: Amount,
5171 sxtx: Amount,
5172
5173 pub const Amount = u3;
5174 };
5175
5176 pub const Decoded = union(enum) {
5177 integer: Integer,
5178 vector: Vector,
5179 };
5180 pub fn decode(inst: @This()) @This().Decoded {
5181 return switch (inst.group.V) {
5182 false => .{ .integer = inst.integer },
5183 true => .{ .vector = inst.vector },
5184 };
5185 }
5186 };
5187
5188 /// Load/store register (unsigned immediate)
5189 pub const RegisterUnsignedImmediate = packed union {
5190 group: @This().Group,
5191 integer: Integer,
5192 vector: Vector,
5193
5194 pub const Group = packed struct {
5195 Rt: Register.Encoded,
5196 Rn: Register.Encoded,
5197 imm12: u12,
5198 opc: u2,
5199 decoded24: u2 = 0b01,
5200 V: bool,
5201 decoded27: u3 = 0b111,
5202 size: u2,
5203 };
5204
5205 pub const Integer = packed union {
5206 group: @This().Group,
5207 strb: Strb,
5208 ldrb: Ldrb,
5209 ldrsb: Ldrsb,
5210 strh: Strh,
5211 ldrh: Ldrh,
5212 ldrsh: Ldrsh,
5213 str: Str,
5214 ldr: Ldr,
5215 ldrsw: Ldrsw,
5216 prfm: Prfm,
5217
5218 pub const Group = packed struct {
5219 Rt: Register.Encoded,
5220 Rn: Register.Encoded,
5221 imm12: u12,
5222 opc: u2,
5223 decoded24: u2 = 0b01,
5224 V: bool = false,
5225 decoded27: u3 = 0b111,
5226 size: Size,
5227 };
5228
5229 /// C6.2.324 STRB (immediate)
5230 pub const Strb = packed struct {
5231 Rt: Register.Encoded,
5232 Rn: Register.Encoded,
5233 imm12: u12,
5234 opc: u2 = 0b00,
5235 decoded24: u2 = 0b01,
5236 V: bool = false,
5237 decoded27: u3 = 0b111,
5238 size: Size = .byte,
5239 };
5240
5241 /// C6.2.170 LDRB (immediate)
5242 pub const Ldrb = packed struct {
5243 Rt: Register.Encoded,
5244 Rn: Register.Encoded,
5245 imm12: u12,
5246 opc: u2 = 0b01,
5247 decoded24: u2 = 0b01,
5248 V: bool = false,
5249 decoded27: u3 = 0b111,
5250 size: Size = .byte,
5251 };
5252
5253 /// C6.2.174 LDRSB (immediate)
5254 pub const Ldrsb = packed struct {
5255 Rt: Register.Encoded,
5256 Rn: Register.Encoded,
5257 imm12: u12,
5258 opc0: u1,
5259 opc1: u1 = 0b1,
5260 decoded24: u2 = 0b01,
5261 V: bool = false,
5262 decoded27: u3 = 0b111,
5263 size: Size = .byte,
5264 };
5265
5266 /// C6.2.326 STRH (immediate)
5267 pub const Strh = packed struct {
5268 Rt: Register.Encoded,
5269 Rn: Register.Encoded,
5270 imm12: u12,
5271 opc: u2 = 0b00,
5272 decoded24: u2 = 0b01,
5273 V: bool = false,
5274 decoded27: u3 = 0b111,
5275 size: Size = .halfword,
5276 };
5277
5278 /// C6.2.172 LDRH (immediate)
5279 pub const Ldrh = packed struct {
5280 Rt: Register.Encoded,
5281 Rn: Register.Encoded,
5282 imm12: u12,
5283 opc: u2 = 0b01,
5284 decoded24: u2 = 0b01,
5285 V: bool = false,
5286 decoded27: u3 = 0b111,
5287 size: Size = .halfword,
5288 };
5289
5290 /// C6.2.176 LDRSH (immediate)
5291 pub const Ldrsh = packed struct {
5292 Rt: Register.Encoded,
5293 Rn: Register.Encoded,
5294 imm12: u12,
5295 opc0: u1,
5296 opc1: u1 = 0b1,
5297 decoded24: u2 = 0b01,
5298 V: bool = false,
5299 decoded27: u3 = 0b111,
5300 size: Size = .halfword,
5301 };
5302
5303 /// C6.2.322 STR (immediate)
5304 pub const Str = packed struct {
5305 Rt: Register.Encoded,
5306 Rn: Register.Encoded,
5307 imm12: u12,
5308 opc: u2 = 0b00,
5309 decoded24: u2 = 0b01,
5310 V: bool = false,
5311 decoded27: u3 = 0b111,
5312 sf: Register.GeneralSize,
5313 size1: u1 = 0b1,
5314 };
5315
5316 /// C6.2.166 LDR (immediate)
5317 pub const Ldr = packed struct {
5318 Rt: Register.Encoded,
5319 Rn: Register.Encoded,
5320 imm12: u12,
5321 opc: u2 = 0b01,
5322 decoded24: u2 = 0b01,
5323 V: bool = false,
5324 decoded27: u3 = 0b111,
5325 sf: Register.GeneralSize,
5326 size1: u1 = 0b1,
5327 };
5328
5329 /// C6.2.178 LDRSW (immediate)
5330 pub const Ldrsw = packed struct {
5331 Rt: Register.Encoded,
5332 Rn: Register.Encoded,
5333 imm12: u12,
5334 opc: u2 = 0b10,
5335 decoded24: u2 = 0b01,
5336 V: bool = false,
5337 decoded27: u3 = 0b111,
5338 size: Size = .word,
5339 };
5340
5341 /// C6.2.247 PRFM (immediate)
5342 pub const Prfm = packed struct {
5343 prfop: PrfOp,
5344 Rn: Register.Encoded,
5345 imm12: u12,
5346 opc: u2 = 0b10,
5347 decoded24: u2 = 0b01,
5348 V: bool = false,
5349 decoded27: u3 = 0b111,
5350 size: Size = .doubleword,
5351 };
5352
5353 pub const Decoded = union(enum) {
5354 unallocated,
5355 strb: Strb,
5356 ldrb: Ldrb,
5357 ldrsb: Ldrsb,
5358 strh: Strh,
5359 ldrh: Ldrh,
5360 ldrsh: Ldrsh,
5361 str: Str,
5362 ldr: Ldr,
5363 ldrsw: Ldrsw,
5364 prfm: Prfm,
5365 };
5366 pub fn decode(inst: @This()) @This().Decoded {
5367 return switch (inst.group.size) {
5368 .byte => switch (inst.group.V) {
5369 false => switch (inst.group.opc) {
5370 0b00 => .{ .strb = inst.strb },
5371 0b01 => .{ .ldrb = inst.ldrb },
5372 0b10, 0b11 => .{ .ldrsb = inst.ldrsb },
5373 },
5374 true => .unallocated,
5375 },
5376 .halfword => switch (inst.group.V) {
5377 false => switch (inst.group.opc) {
5378 0b00 => .{ .strh = inst.strh },
5379 0b01 => .{ .ldrh = inst.ldrh },
5380 0b10, 0b11 => .{ .ldrsh = inst.ldrsh },
5381 },
5382 true => .unallocated,
5383 },
5384 .word => switch (inst.group.V) {
5385 false => switch (inst.group.opc) {
5386 0b00 => .{ .str = inst.str },
5387 0b01 => .{ .ldr = inst.ldr },
5388 0b10 => .{ .ldrsw = inst.ldrsw },
5389 0b11 => .unallocated,
5390 },
5391 true => .unallocated,
5392 },
5393 .doubleword => switch (inst.group.V) {
5394 false => switch (inst.group.opc) {
5395 0b00 => .{ .str = inst.str },
5396 0b01 => .{ .ldr = inst.ldr },
5397 0b10 => .{ .prfm = inst.prfm },
5398 0b11 => .unallocated,
5399 },
5400 true => .unallocated,
5401 },
5402 };
5403 }
5404 };
5405
5406 pub const Vector = packed union {
5407 group: @This().Group,
5408 str: Str,
5409 ldr: Ldr,
5410
5411 pub const Group = packed struct {
5412 Rt: Register.Encoded,
5413 Rn: Register.Encoded,
5414 imm12: u12,
5415 opc0: L,
5416 opc1: Opc1,
5417 decoded24: u2 = 0b01,
5418 V: bool = true,
5419 decoded27: u3 = 0b111,
5420 size: Vector.Size,
5421 };
5422
5423 /// C7.2.331 STR (immediate, SIMD&FP)
5424 pub const Str = packed struct {
5425 Rt: Register.Encoded,
5426 Rn: Register.Encoded,
5427 imm12: u12,
5428 opc0: L = .store,
5429 opc1: Opc1,
5430 decoded24: u2 = 0b01,
5431 V: bool = true,
5432 decoded27: u3 = 0b111,
5433 size: Vector.Size,
5434 };
5435
5436 /// C7.2.191 LDR (immediate, SIMD&FP)
5437 pub const Ldr = packed struct {
5438 Rt: Register.Encoded,
5439 Rn: Register.Encoded,
5440 imm12: u12,
5441 opc0: L = .load,
5442 opc1: Opc1,
5443 decoded24: u2 = 0b01,
5444 V: bool = true,
5445 decoded27: u3 = 0b111,
5446 size: Vector.Size,
5447 };
5448
5449 pub const Opc1 = packed struct {
5450 encoded: u1,
5451
5452 pub fn encode(ss: Register.ScalarSize) Opc1 {
5453 return .{ .encoded = switch (ss) {
5454 .byte, .half, .single, .double => 0b0,
5455 .quad => 0b1,
5456 } };
5457 }
5458
5459 pub fn decode(enc_opc1: Opc1, enc_size: Vector.Size) Register.ScalarSize {
5460 return switch (enc_size.encoded) {
5461 0b00 => switch (enc_opc1.encoded) {
5462 0b0 => .byte,
5463 0b1 => .quad,
5464 },
5465 0b01 => switch (enc_opc1.encoded) {
5466 0b0 => .half,
5467 0b1 => unreachable,
5468 },
5469 0b10 => switch (enc_opc1.encoded) {
5470 0b0 => .single,
5471 0b1 => unreachable,
5472 },
5473 0b11 => switch (enc_opc1.encoded) {
5474 0b0 => .double,
5475 0b1 => unreachable,
5476 },
5477 };
5478 }
5479 };
5480
5481 pub const Size = packed struct {
5482 encoded: u2,
5483
5484 pub fn encode(ss: Register.ScalarSize) Vector.Size {
5485 return .{ .encoded = switch (ss) {
5486 .byte, .quad => 0b00,
5487 .half => 0b01,
5488 .single => 0b10,
5489 .double => 0b11,
5490 } };
5491 }
5492 };
5493
5494 pub const Decoded = union(enum) {
5495 unallocated,
5496 str: Str,
5497 ldr: Ldr,
5498 };
5499 pub fn decode(inst: @This()) @This().Decoded {
5500 return switch (inst.group.size.encoded) {
5501 0b00 => switch (inst.group.opc0) {
5502 .store => .{ .str = inst.str },
5503 .load => .{ .ldr = inst.ldr },
5504 },
5505 0b01, 0b10, 0b11 => switch (inst.group.opc1.encoded) {
5506 0b0 => switch (inst.group.opc0) {
5507 .store => .{ .str = inst.str },
5508 .load => .{ .ldr = inst.ldr },
5509 },
5510 0b1 => .unallocated,
5511 },
5512 };
5513 }
5514 };
5515
5516 pub const Decoded = union(enum) {
5517 integer: Integer,
5518 vector: Vector,
5519 };
5520 pub fn decode(inst: @This()) @This().Decoded {
5521 return switch (inst.group.V) {
5522 false => .{ .integer = inst.integer },
5523 true => .{ .vector = inst.vector },
5524 };
5525 }
5526 };
5527
5528 pub const L = enum(u1) {
5529 store = 0b0,
5530 load = 0b1,
5531 };
5532
5533 pub const Size = enum(u2) {
5534 byte = 0b00,
5535 halfword = 0b01,
5536 word = 0b10,
5537 doubleword = 0b11,
5538 };
5539
5540 pub const VectorSize = enum(u2) {
5541 single = 0b00,
5542 double = 0b01,
5543 quad = 0b10,
5544 _,
5545
5546 pub fn decode(vs: VectorSize) Register.ScalarSize {
5547 return switch (vs) {
5548 .single => .single,
5549 .double => .double,
5550 .quad => .quad,
5551 _ => unreachable,
5552 };
5553 }
5554
5555 pub fn encode(ss: Register.ScalarSize) VectorSize {
5556 return switch (ss) {
5557 else => unreachable,
5558 .single => .single,
5559 .double => .double,
5560 .quad => .quad,
5561 };
5562 }
5563 };
5564
5565 pub const PrfOp = packed struct {
5566 policy: Policy,
5567 target: Target,
5568 type: Type,
5569
5570 pub const Policy = enum(u1) {
5571 keep = 0b0,
5572 strm = 0b1,
5573 };
5574
5575 pub const Target = enum(u2) {
5576 l1 = 0b00,
5577 l2 = 0b01,
5578 l3 = 0b10,
5579 _,
5580 };
5581
5582 pub const Type = enum(u2) {
5583 pld = 0b00,
5584 pli = 0b01,
5585 pst = 0b10,
5586 _,
5587 };
5588
5589 pub const pldl1keep: PrfOp = .{ .type = .pld, .target = .l1, .policy = .keep };
5590 pub const pldl1strm: PrfOp = .{ .type = .pld, .target = .l1, .policy = .strm };
5591 pub const pldl2keep: PrfOp = .{ .type = .pld, .target = .l2, .policy = .keep };
5592 pub const pldl2strm: PrfOp = .{ .type = .pld, .target = .l2, .policy = .strm };
5593 pub const pldl3keep: PrfOp = .{ .type = .pld, .target = .l3, .policy = .keep };
5594 pub const pldl3strm: PrfOp = .{ .type = .pld, .target = .l3, .policy = .strm };
5595 pub const plil1keep: PrfOp = .{ .type = .pli, .target = .l1, .policy = .keep };
5596 pub const plil1strm: PrfOp = .{ .type = .pli, .target = .l1, .policy = .strm };
5597 pub const plil2keep: PrfOp = .{ .type = .pli, .target = .l2, .policy = .keep };
5598 pub const plil2strm: PrfOp = .{ .type = .pli, .target = .l2, .policy = .strm };
5599 pub const plil3keep: PrfOp = .{ .type = .pli, .target = .l3, .policy = .keep };
5600 pub const plil3strm: PrfOp = .{ .type = .pli, .target = .l3, .policy = .strm };
5601 pub const pstl1keep: PrfOp = .{ .type = .pst, .target = .l1, .policy = .keep };
5602 pub const pstl1strm: PrfOp = .{ .type = .pst, .target = .l1, .policy = .strm };
5603 pub const pstl2keep: PrfOp = .{ .type = .pst, .target = .l2, .policy = .keep };
5604 pub const pstl2strm: PrfOp = .{ .type = .pst, .target = .l2, .policy = .strm };
5605 pub const pstl3keep: PrfOp = .{ .type = .pst, .target = .l3, .policy = .keep };
5606 pub const pstl3strm: PrfOp = .{ .type = .pst, .target = .l3, .policy = .strm_ };
5607 };
5608
5609 pub const Decoded = union(enum) {
5610 unallocated,
5611 register_literal: RegisterLiteral,
5612 memory: Memory,
5613 no_allocate_pair_offset: NoAllocatePairOffset,
5614 register_pair_post_indexed: RegisterPairPostIndexed,
5615 register_pair_offset: RegisterPairOffset,
5616 register_pair_pre_indexed: RegisterPairPreIndexed,
5617 register_unscaled_immediate: RegisterUnscaledImmediate,
5618 register_immediate_post_indexed: RegisterImmediatePostIndexed,
5619 register_unprivileged: RegisterUnprivileged,
5620 register_immediate_pre_indexed: RegisterImmediatePreIndexed,
5621 register_register_offset: RegisterRegisterOffset,
5622 register_unsigned_immediate: RegisterUnsignedImmediate,
5623 };
5624 pub fn decode(inst: @This()) @This().Decoded {
5625 return switch (inst.group.op0) {
5626 else => .unallocated,
5627 0b0010, 0b0110, 0b1010, 0b1110 => switch (inst.group.op2) {
5628 0b00 => .{ .no_allocate_pair_offset = inst.no_allocate_pair_offset },
5629 0b01 => .{ .register_pair_post_indexed = inst.register_pair_post_indexed },
5630 0b10 => .{ .register_pair_offset = inst.register_pair_offset },
5631 0b11 => .{ .register_pair_pre_indexed = inst.register_pair_pre_indexed },
5632 },
5633 0b0011, 0b0111, 0b1011, 0b1111 => switch (inst.group.op2) {
5634 0b00...0b01 => switch (inst.group.op3) {
5635 0b000000...0b011111 => switch (inst.group.op4) {
5636 0b00 => .{ .register_unscaled_immediate = inst.register_unscaled_immediate },
5637 0b01 => .{ .register_immediate_post_indexed = inst.register_immediate_post_indexed },
5638 0b10 => .{ .register_unprivileged = inst.register_unprivileged },
5639 0b11 => .{ .register_immediate_pre_indexed = inst.register_immediate_pre_indexed },
5640 },
5641 0b100000...0b111111 => switch (inst.group.op4) {
5642 0b00 => .unallocated,
5643 0b10 => .{ .register_register_offset = inst.register_register_offset },
5644 0b01, 0b11 => .unallocated,
5645 },
5646 },
5647 0b10...0b11 => .{ .register_unsigned_immediate = inst.register_unsigned_immediate },
5648 },
5649 };
5650 }
5651 };
5652
5653 /// C4.1.89 Data Processing -- Register
5654 pub const DataProcessingRegister = packed union {
5655 group: @This().Group,
5656 data_processing_two_source: DataProcessingTwoSource,
5657 data_processing_one_source: DataProcessingOneSource,
5658 logical_shifted_register: LogicalShiftedRegister,
5659 add_subtract_shifted_register: AddSubtractShiftedRegister,
5660 add_subtract_extended_register: AddSubtractExtendedRegister,
5661 add_subtract_with_carry: AddSubtractWithCarry,
5662 rotate_right_into_flags: RotateRightIntoFlags,
5663 evaluate_into_flags: EvaluateIntoFlags,
5664 conditional_compare_register: ConditionalCompareRegister,
5665 conditional_compare_immediate: ConditionalCompareImmediate,
5666 conditional_select: ConditionalSelect,
5667 data_processing_three_source: DataProcessingThreeSource,
5668
5669 /// Table C4-90 Encoding table for the Data Processing -- Register group
5670 pub const Group = packed struct {
5671 encoded0: u10,
5672 op3: u6,
5673 encoded16: u5,
5674 op2: u4,
5675 decoded25: u3 = 0b101,
5676 op1: u1,
5677 encoded29: u1,
5678 op0: u1,
5679 encoded31: u1,
5680 };
5681
5682 /// Data-processing (2 source)
5683 pub const DataProcessingTwoSource = packed union {
5684 group: @This().Group,
5685 udiv: Udiv,
5686 sdiv: Sdiv,
5687 lslv: Lslv,
5688 lsrv: Lsrv,
5689 asrv: Asrv,
5690 rorv: Rorv,
5691
5692 pub const Group = packed struct {
5693 Rd: Register.Encoded,
5694 Rn: Register.Encoded,
5695 opcode: u6,
5696 Rm: Register.Encoded,
5697 decoded21: u8 = 0b11010110,
5698 S: bool,
5699 decoded30: u1 = 0b0,
5700 sf: Register.GeneralSize,
5701 };
5702
5703 /// C6.2.388 UDIV
5704 pub const Udiv = packed struct {
5705 Rd: Register.Encoded,
5706 Rn: Register.Encoded,
5707 o1: DivOp = .udiv,
5708 decoded11: u5 = 0b00001,
5709 Rm: Register.Encoded,
5710 decoded21: u8 = 0b11010110,
5711 S: bool = false,
5712 decoded30: u1 = 0b0,
5713 sf: Register.GeneralSize,
5714 };
5715
5716 /// C6.2.270 SDIV
5717 pub const Sdiv = packed struct {
5718 Rd: Register.Encoded,
5719 Rn: Register.Encoded,
5720 o1: DivOp = .sdiv,
5721 decoded11: u5 = 0b00001,
5722 Rm: Register.Encoded,
5723 decoded21: u8 = 0b11010110,
5724 S: bool = false,
5725 decoded30: u1 = 0b0,
5726 sf: Register.GeneralSize,
5727 };
5728
5729 /// C6.2.214 LSLV
5730 pub const Lslv = packed struct {
5731 Rd: Register.Encoded,
5732 Rn: Register.Encoded,
5733 op2: ShiftOp = .lslv,
5734 decoded12: u4 = 0b0010,
5735 Rm: Register.Encoded,
5736 decoded21: u8 = 0b11010110,
5737 S: bool = false,
5738 decoded30: u1 = 0b0,
5739 sf: Register.GeneralSize,
5740 };
5741
5742 /// C6.2.217 LSRV
5743 pub const Lsrv = packed struct {
5744 Rd: Register.Encoded,
5745 Rn: Register.Encoded,
5746 op2: ShiftOp = .lsrv,
5747 decoded12: u4 = 0b0010,
5748 Rm: Register.Encoded,
5749 decoded21: u8 = 0b11010110,
5750 S: bool = false,
5751 decoded30: u1 = 0b0,
5752 sf: Register.GeneralSize,
5753 };
5754
5755 /// C6.2.18 ASRV
5756 pub const Asrv = packed struct {
5757 Rd: Register.Encoded,
5758 Rn: Register.Encoded,
5759 op2: ShiftOp = .asrv,
5760 decoded12: u4 = 0b0010,
5761 Rm: Register.Encoded,
5762 decoded21: u8 = 0b11010110,
5763 S: bool = false,
5764 decoded30: u1 = 0b0,
5765 sf: Register.GeneralSize,
5766 };
5767
5768 /// C6.2.263 RORV
5769 pub const Rorv = packed struct {
5770 Rd: Register.Encoded,
5771 Rn: Register.Encoded,
5772 op2: ShiftOp = .rorv,
5773 decoded12: u4 = 0b0010,
5774 Rm: Register.Encoded,
5775 decoded21: u8 = 0b11010110,
5776 S: bool = false,
5777 decoded30: u1 = 0b0,
5778 sf: Register.GeneralSize,
5779 };
5780
5781 pub const DivOp = enum(u1) {
5782 udiv = 0b0,
5783 sdiv = 0b1,
5784 };
5785
5786 pub const ShiftOp = enum(u2) {
5787 lslv = 0b00,
5788 lsrv = 0b01,
5789 asrv = 0b10,
5790 rorv = 0b11,
5791 };
5792
5793 pub const Decoded = union(enum) {
5794 unallocated,
5795 udiv: Udiv,
5796 sdiv: Sdiv,
5797 lslv: Lslv,
5798 lsrv: Lsrv,
5799 asrv: Asrv,
5800 rorv: Rorv,
5801 };
5802 pub fn decode(inst: @This()) @This().Decoded {
5803 return switch (inst.group.S) {
5804 false => switch (inst.group.opcode) {
5805 else => .unallocated,
5806 0b000010 => .{ .udiv = inst.udiv },
5807 0b000011 => .{ .sdiv = inst.sdiv },
5808 0b001000 => .{ .lslv = inst.lslv },
5809 0b001001 => .{ .lsrv = inst.lsrv },
5810 0b001010 => .{ .asrv = inst.asrv },
5811 0b001011 => .{ .rorv = inst.rorv },
5812 },
5813 true => .unallocated,
5814 };
5815 }
5816 };
5817
5818 /// Data-processing (1 source)
5819 pub const DataProcessingOneSource = packed union {
5820 group: @This().Group,
5821 rbit: Rbit,
5822 rev16: Rev16,
5823 rev32: Rev32,
5824 rev: Rev,
5825 clz: Clz,
5826 cls: Cls,
5827
5828 pub const Group = packed struct {
5829 Rd: Register.Encoded,
5830 Rn: Register.Encoded,
5831 opcode: u6,
5832 opcode2: u5,
5833 decoded21: u8 = 0b11010110,
5834 S: bool,
5835 decoded30: u1 = 0b1,
5836 sf: Register.GeneralSize,
5837 };
5838
5839 /// C6.2.253 RBIT
5840 pub const Rbit = packed struct {
5841 Rd: Register.Encoded,
5842 Rn: Register.Encoded,
5843 decoded10: u2 = 0b00,
5844 decoded12: u4 = 0b0000,
5845 decoded16: u5 = 0b00000,
5846 decoded21: u8 = 0b11010110,
5847 S: bool = false,
5848 decoded30: u1 = 0b1,
5849 sf: Register.GeneralSize,
5850 };
5851
5852 /// C6.2.257 REV16
5853 pub const Rev16 = packed struct {
5854 Rd: Register.Encoded,
5855 Rn: Register.Encoded,
5856 opc: u2 = 0b01,
5857 decoded12: u4 = 0b0000,
5858 decoded16: u5 = 0b00000,
5859 decoded21: u8 = 0b11010110,
5860 S: bool = false,
5861 decoded30: u1 = 0b1,
5862 sf: Register.GeneralSize,
5863 };
5864
5865 /// C6.2.258 REV32
5866 pub const Rev32 = packed struct {
5867 Rd: Register.Encoded,
5868 Rn: Register.Encoded,
5869 opc: u2 = 0b10,
5870 decoded12: u4 = 0b0000,
5871 decoded16: u5 = 0b00000,
5872 decoded21: u8 = 0b11010110,
5873 S: bool = false,
5874 decoded30: u1 = 0b1,
5875 sf: Register.GeneralSize = .doubleword,
5876 };
5877
5878 /// C6.2.256 REV
5879 pub const Rev = packed struct {
5880 Rd: Register.Encoded,
5881 Rn: Register.Encoded,
5882 opc0: Register.GeneralSize,
5883 opc1: u1 = 0b1,
5884 decoded12: u4 = 0b0000,
5885 decoded16: u5 = 0b00000,
5886 decoded21: u8 = 0b11010110,
5887 S: bool = false,
5888 decoded30: u1 = 0b1,
5889 sf: Register.GeneralSize,
5890 };
5891
5892 /// C6.2.58 CLZ
5893 pub const Clz = packed struct {
5894 Rd: Register.Encoded,
5895 Rn: Register.Encoded,
5896 op: u1 = 0b0,
5897 decoded11: u5 = 0b00010,
5898 decoded16: u5 = 0b00000,
5899 decoded21: u8 = 0b11010110,
5900 S: bool = false,
5901 decoded30: u1 = 0b1,
5902 sf: Register.GeneralSize,
5903 };
5904
5905 /// C6.2.57 CLS
5906 pub const Cls = packed struct {
5907 Rd: Register.Encoded,
5908 Rn: Register.Encoded,
5909 op: u1 = 0b1,
5910 decoded11: u5 = 0b00010,
5911 decoded16: u5 = 0b00000,
5912 decoded21: u8 = 0b11010110,
5913 S: bool = false,
5914 decoded30: u1 = 0b1,
5915 sf: Register.GeneralSize,
5916 };
5917
5918 pub const Decoded = union(enum) {
5919 unallocated,
5920 rbit: Rbit,
5921 rev16: Rev16,
5922 rev32: Rev32,
5923 rev: Rev,
5924 clz: Clz,
5925 cls: Cls,
5926 };
5927 pub fn decode(inst: @This()) @This().Decoded {
5928 return switch (inst.group.S) {
5929 true => .unallocated,
5930 false => switch (inst.group.opcode2) {
5931 else => .unallocated,
5932 0b00000 => switch (inst.group.opcode) {
5933 else => .unallocated,
5934 0b000000 => .{ .rbit = inst.rbit },
5935 0b000001 => .{ .rev16 = inst.rev16 },
5936 0b000010 => switch (inst.group.sf) {
5937 .word => .{ .rev = inst.rev },
5938 .doubleword => .{ .rev32 = inst.rev32 },
5939 },
5940 0b000011 => switch (inst.group.sf) {
5941 .word => .unallocated,
5942 .doubleword => .{ .rev = inst.rev },
5943 },
5944 0b000100 => .{ .clz = inst.clz },
5945 0b000101 => .{ .cls = inst.cls },
5946 },
5947 },
5948 };
5949 }
5950 };
5951
5952 /// Logical (shifted register)
5953 pub const LogicalShiftedRegister = packed union {
5954 group: @This().Group,
5955 @"and": And,
5956 bic: Bic,
5957 orr: Orr,
5958 orn: Orn,
5959 eor: Eor,
5960 eon: Eon,
5961 ands: Ands,
5962 bics: Bics,
5963
5964 pub const Group = packed struct {
5965 Rd: Register.Encoded,
5966 Rn: Register.Encoded,
5967 imm6: Shift.Amount,
5968 Rm: Register.Encoded,
5969 N: bool,
5970 shift: Shift.Op,
5971 decoded24: u5 = 0b01010,
5972 opc: LogicalOpc,
5973 sf: Register.GeneralSize,
5974 };
5975
5976 /// C6.2.13 AND (shifted register)
5977 pub const And = packed struct {
5978 Rd: Register.Encoded,
5979 Rn: Register.Encoded,
5980 imm6: Shift.Amount,
5981 Rm: Register.Encoded,
5982 N: bool = false,
5983 shift: Shift.Op,
5984 decoded24: u5 = 0b01010,
5985 opc: LogicalOpc = .@"and",
5986 sf: Register.GeneralSize,
5987 };
5988
5989 /// C6.2.32 BIC (shifted register)
5990 pub const Bic = packed struct {
5991 Rd: Register.Encoded,
5992 Rn: Register.Encoded,
5993 imm6: Shift.Amount,
5994 Rm: Register.Encoded,
5995 N: bool = true,
5996 shift: Shift.Op,
5997 decoded24: u5 = 0b01010,
5998 opc: LogicalOpc = .@"and",
5999 sf: Register.GeneralSize,
6000 };
6001
6002 /// C6.2.241 ORR (shifted register)
6003 pub const Orr = packed struct {
6004 Rd: Register.Encoded,
6005 Rn: Register.Encoded,
6006 imm6: Shift.Amount,
6007 Rm: Register.Encoded,
6008 N: bool = false,
6009 shift: Shift.Op,
6010 decoded24: u5 = 0b01010,
6011 opc: LogicalOpc = .orr,
6012 sf: Register.GeneralSize,
6013 };
6014
6015 /// C6.2.239 ORN (shifted register)
6016 pub const Orn = packed struct {
6017 Rd: Register.Encoded,
6018 Rn: Register.Encoded,
6019 imm6: Shift.Amount,
6020 Rm: Register.Encoded,
6021 N: bool = true,
6022 shift: Shift.Op,
6023 decoded24: u5 = 0b01010,
6024 opc: LogicalOpc = .orr,
6025 sf: Register.GeneralSize,
6026 };
6027
6028 /// C6.2.120 EOR (shifted register)
6029 pub const Eor = packed struct {
6030 Rd: Register.Encoded,
6031 Rn: Register.Encoded,
6032 imm6: Shift.Amount,
6033 Rm: Register.Encoded,
6034 N: bool = false,
6035 shift: Shift.Op,
6036 decoded24: u5 = 0b01010,
6037 opc: LogicalOpc = .eor,
6038 sf: Register.GeneralSize,
6039 };
6040
6041 /// C6.2.118 EON (shifted register)
6042 pub const Eon = packed struct {
6043 Rd: Register.Encoded,
6044 Rn: Register.Encoded,
6045 imm6: Shift.Amount,
6046 Rm: Register.Encoded,
6047 N: bool = true,
6048 shift: Shift.Op,
6049 decoded24: u5 = 0b01010,
6050 opc: LogicalOpc = .eor,
6051 sf: Register.GeneralSize,
6052 };
6053
6054 /// C6.2.15 ANDS (shifted register)
6055 pub const Ands = packed struct {
6056 Rd: Register.Encoded,
6057 Rn: Register.Encoded,
6058 imm6: Shift.Amount,
6059 Rm: Register.Encoded,
6060 N: bool = false,
6061 shift: Shift.Op,
6062 decoded24: u5 = 0b01010,
6063 opc: LogicalOpc = .ands,
6064 sf: Register.GeneralSize,
6065 };
6066
6067 /// C6.2.33 BICS (shifted register)
6068 pub const Bics = packed struct {
6069 Rd: Register.Encoded,
6070 Rn: Register.Encoded,
6071 imm6: Shift.Amount,
6072 Rm: Register.Encoded,
6073 N: bool = true,
6074 shift: Shift.Op,
6075 decoded24: u5 = 0b01010,
6076 opc: LogicalOpc = .ands,
6077 sf: Register.GeneralSize,
6078 };
6079
6080 pub const Decoded = union(enum) {
6081 unallocated,
6082 @"and": And,
6083 bic: Bic,
6084 orr: Orr,
6085 orn: Orn,
6086 eor: Eor,
6087 eon: Eon,
6088 ands: Ands,
6089 bics: Bics,
6090 };
6091 pub fn decode(inst: @This()) @This().Decoded {
6092 return if (inst.group.sf == .word and @as(u1, @truncate(inst.group.imm6 >> 5)) == 0b1)
6093 .unallocated
6094 else switch (inst.group.opc) {
6095 .@"and" => switch (inst.group.N) {
6096 false => .{ .@"and" = inst.@"and" },
6097 true => .{ .bic = inst.bic },
6098 },
6099 .orr => switch (inst.group.N) {
6100 false => .{ .orr = inst.orr },
6101 true => .{ .orn = inst.orn },
6102 },
6103 .eor => switch (inst.group.N) {
6104 false => .{ .eor = inst.eor },
6105 true => .{ .eon = inst.eon },
6106 },
6107 .ands => switch (inst.group.N) {
6108 false => .{ .ands = inst.ands },
6109 true => .{ .bics = inst.bics },
6110 },
6111 };
6112 }
6113 };
6114
6115 /// Add/subtract (shifted register)
6116 pub const AddSubtractShiftedRegister = packed union {
6117 group: @This().Group,
6118 add: Add,
6119 adds: Adds,
6120 sub: Sub,
6121 subs: Subs,
6122
6123 pub const Group = packed struct {
6124 Rd: Register.Encoded,
6125 Rn: Register.Encoded,
6126 imm6: Shift.Amount,
6127 Rm: Register.Encoded,
6128 decoded21: u1 = 0b0,
6129 shift: Shift.Op,
6130 decoded24: u5 = 0b01011,
6131 S: bool,
6132 op: AddSubtractOp,
6133 sf: Register.GeneralSize,
6134 };
6135
6136 /// C6.2.5 ADD (shifted register)
6137 pub const Add = packed struct {
6138 Rd: Register.Encoded,
6139 Rn: Register.Encoded,
6140 imm6: Shift.Amount,
6141 Rm: Register.Encoded,
6142 decoded21: u1 = 0b0,
6143 shift: Shift.Op,
6144 decoded24: u5 = 0b01011,
6145 S: bool = false,
6146 op: AddSubtractOp = .add,
6147 sf: Register.GeneralSize,
6148 };
6149
6150 /// C6.2.9 ADDS (shifted register)
6151 pub const Adds = packed struct {
6152 Rd: Register.Encoded,
6153 Rn: Register.Encoded,
6154 imm6: Shift.Amount,
6155 Rm: Register.Encoded,
6156 decoded21: u1 = 0b0,
6157 shift: Shift.Op,
6158 decoded24: u5 = 0b01011,
6159 S: bool = true,
6160 op: AddSubtractOp = .add,
6161 sf: Register.GeneralSize,
6162 };
6163
6164 /// C6.2.5 SUB (shifted register)
6165 pub const Sub = packed struct {
6166 Rd: Register.Encoded,
6167 Rn: Register.Encoded,
6168 imm6: Shift.Amount,
6169 Rm: Register.Encoded,
6170 decoded21: u1 = 0b0,
6171 shift: Shift.Op,
6172 decoded24: u5 = 0b01011,
6173 S: bool = false,
6174 op: AddSubtractOp = .sub,
6175 sf: Register.GeneralSize,
6176 };
6177
6178 /// C6.2.9 SUBS (shifted register)
6179 pub const Subs = packed struct {
6180 Rd: Register.Encoded,
6181 Rn: Register.Encoded,
6182 imm6: Shift.Amount,
6183 Rm: Register.Encoded,
6184 decoded21: u1 = 0b0,
6185 shift: Shift.Op,
6186 decoded24: u5 = 0b01011,
6187 S: bool = true,
6188 op: AddSubtractOp = .sub,
6189 sf: Register.GeneralSize,
6190 };
6191
6192 pub const Decoded = union(enum) {
6193 unallocated,
6194 add: Add,
6195 adds: Adds,
6196 sub: Sub,
6197 subs: Subs,
6198 };
6199 pub fn decode(inst: @This()) @This().Decoded {
6200 return switch (inst.group.shift) {
6201 .ror => .unallocated,
6202 .lsl, .lsr, .asr => if (inst.group.sf == .word and @as(u1, @truncate(inst.group.imm6 >> 5)) == 0b1)
6203 .unallocated
6204 else switch (inst.group.op) {
6205 .add => switch (inst.group.S) {
6206 false => .{ .add = inst.add },
6207 true => .{ .adds = inst.adds },
6208 },
6209 .sub => switch (inst.group.S) {
6210 false => .{ .sub = inst.sub },
6211 true => .{ .subs = inst.subs },
6212 },
6213 },
6214 };
6215 }
6216 };
6217
6218 /// Add/subtract (extended register)
6219 pub const AddSubtractExtendedRegister = packed union {
6220 group: @This().Group,
6221 add: Add,
6222 adds: Adds,
6223 sub: Sub,
6224 subs: Subs,
6225
6226 pub const Group = packed struct {
6227 Rd: Register.Encoded,
6228 Rn: Register.Encoded,
6229 imm3: Extend.Amount,
6230 option: Option,
6231 Rm: Register.Encoded,
6232 decoded21: u1 = 0b1,
6233 opt: u2,
6234 decoded24: u5 = 0b01011,
6235 S: bool,
6236 op: AddSubtractOp,
6237 sf: Register.GeneralSize,
6238 };
6239
6240 /// C6.2.3 ADD (extended register)
6241 pub const Add = packed struct {
6242 Rd: Register.Encoded,
6243 Rn: Register.Encoded,
6244 imm3: Extend.Amount,
6245 option: Option,
6246 Rm: Register.Encoded,
6247 decoded21: u1 = 0b1,
6248 opt: u2 = 0b00,
6249 decoded24: u5 = 0b01011,
6250 S: bool = false,
6251 op: AddSubtractOp = .add,
6252 sf: Register.GeneralSize,
6253 };
6254
6255 /// C6.2.7 ADDS (extended register)
6256 pub const Adds = packed struct {
6257 Rd: Register.Encoded,
6258 Rn: Register.Encoded,
6259 imm3: Extend.Amount,
6260 option: Option,
6261 Rm: Register.Encoded,
6262 decoded21: u1 = 0b1,
6263 opt: u2 = 0b00,
6264 decoded24: u5 = 0b01011,
6265 S: bool = true,
6266 op: AddSubtractOp = .add,
6267 sf: Register.GeneralSize,
6268 };
6269
6270 /// C6.2.356 SUB (extended register)
6271 pub const Sub = packed struct {
6272 Rd: Register.Encoded,
6273 Rn: Register.Encoded,
6274 imm3: Extend.Amount,
6275 option: Option,
6276 Rm: Register.Encoded,
6277 decoded21: u1 = 0b1,
6278 opt: u2 = 0b00,
6279 decoded24: u5 = 0b01011,
6280 S: bool = false,
6281 op: AddSubtractOp = .sub,
6282 sf: Register.GeneralSize,
6283 };
6284
6285 /// C6.2.362 SUBS (extended register)
6286 pub const Subs = packed struct {
6287 Rd: Register.Encoded,
6288 Rn: Register.Encoded,
6289 imm3: Extend.Amount,
6290 option: Option,
6291 Rm: Register.Encoded,
6292 decoded21: u1 = 0b1,
6293 opt: u2 = 0b00,
6294 decoded24: u5 = 0b01011,
6295 S: bool = true,
6296 op: AddSubtractOp = .sub,
6297 sf: Register.GeneralSize,
6298 };
6299
6300 pub const Option = enum(u3) {
6301 uxtb = 0b000,
6302 uxth = 0b001,
6303 uxtw = 0b010,
6304 uxtx = 0b011,
6305 sxtb = 0b100,
6306 sxth = 0b101,
6307 sxtw = 0b110,
6308 sxtx = 0b111,
6309
6310 pub fn sf(option: Option) Register.GeneralSize {
6311 return switch (option) {
6312 .uxtb, .uxth, .uxtw, .sxtb, .sxth, .sxtw => .word,
6313 .uxtx, .sxtx => .doubleword,
6314 };
6315 }
6316 };
6317
6318 pub const Extend = union(Option) {
6319 uxtb: Amount,
6320 uxth: Amount,
6321 uxtw: Amount,
6322 uxtx: Amount,
6323 sxtb: Amount,
6324 sxth: Amount,
6325 sxtw: Amount,
6326 sxtx: Amount,
6327
6328 pub const Amount = u3;
6329 };
6330
6331 pub const Decoded = union(enum) {
6332 unallocated,
6333 add: Add,
6334 adds: Adds,
6335 sub: Sub,
6336 subs: Subs,
6337 };
6338 pub fn decode(inst: @This()) @This().Decoded {
6339 return switch (inst.group.imm3) {
6340 0b101 => .unallocated,
6341 0b110...0b111 => .unallocated,
6342 0b000...0b100 => switch (inst.group.opt) {
6343 0b01 => .unallocated,
6344 0b10...0b11 => .unallocated,
6345 0b00 => switch (inst.group.op) {
6346 .add => switch (inst.group.S) {
6347 false => .{ .add = inst.add },
6348 true => .{ .adds = inst.adds },
6349 },
6350 .sub => switch (inst.group.S) {
6351 false => .{ .sub = inst.sub },
6352 true => .{ .subs = inst.subs },
6353 },
6354 },
6355 },
6356 };
6357 }
6358 };
6359
6360 /// Add/subtract (with carry)
6361 pub const AddSubtractWithCarry = packed union {
6362 group: @This().Group,
6363 adc: Adc,
6364 adcs: Adcs,
6365 sbc: Sbc,
6366 sbcs: Sbcs,
6367
6368 pub const Group = packed struct {
6369 Rd: Register.Encoded,
6370 Rn: Register.Encoded,
6371 decoded10: u6 = 0b000000,
6372 Rm: Register.Encoded,
6373 decoded21: u8 = 0b11010000,
6374 S: bool,
6375 op: Op,
6376 sf: Register.GeneralSize,
6377 };
6378
6379 /// C6.2.1 ADC
6380 pub const Adc = packed struct {
6381 Rd: Register.Encoded,
6382 Rn: Register.Encoded,
6383 decoded10: u6 = 0b000000,
6384 Rm: Register.Encoded,
6385 decoded21: u8 = 0b11010000,
6386 S: bool = false,
6387 op: Op = .adc,
6388 sf: Register.GeneralSize,
6389 };
6390
6391 /// C6.2.2 ADCS
6392 pub const Adcs = packed struct {
6393 Rd: Register.Encoded,
6394 Rn: Register.Encoded,
6395 decoded10: u6 = 0b000000,
6396 Rm: Register.Encoded,
6397 decoded21: u8 = 0b11010000,
6398 S: bool = true,
6399 op: Op = .adc,
6400 sf: Register.GeneralSize,
6401 };
6402
6403 /// C6.2.265 SBC
6404 pub const Sbc = packed struct {
6405 Rd: Register.Encoded,
6406 Rn: Register.Encoded,
6407 decoded10: u6 = 0b000000,
6408 Rm: Register.Encoded,
6409 decoded21: u8 = 0b11010000,
6410 S: bool = false,
6411 op: Op = .sbc,
6412 sf: Register.GeneralSize,
6413 };
6414
6415 /// C6.2.266 SBCS
6416 pub const Sbcs = packed struct {
6417 Rd: Register.Encoded,
6418 Rn: Register.Encoded,
6419 decoded10: u6 = 0b000000,
6420 Rm: Register.Encoded,
6421 decoded21: u8 = 0b11010000,
6422 S: bool = true,
6423 op: Op = .sbc,
6424 sf: Register.GeneralSize,
6425 };
6426
6427 pub const Op = enum(u1) {
6428 adc = 0b0,
6429 sbc = 0b1,
6430 };
6431
6432 pub const Decoded = union(enum) {
6433 adc: Adc,
6434 adcs: Adcs,
6435 sbc: Sbc,
6436 sbcs: Sbcs,
6437 };
6438 pub fn decode(inst: @This()) @This().Decoded {
6439 return switch (inst.group.op) {
6440 .adc => switch (inst.group.S) {
6441 false => .{ .adc = inst.adc },
6442 true => .{ .adcs = inst.adcs },
6443 },
6444 .sbc => switch (inst.group.S) {
6445 false => .{ .sbc = inst.sbc },
6446 true => .{ .sbcs = inst.sbcs },
6447 },
6448 };
6449 }
6450 };
6451
6452 /// Rotate right into flags
6453 pub const RotateRightIntoFlags = packed union {
6454 group: @This().Group,
6455
6456 pub const Group = packed struct {
6457 mask: Nzcv,
6458 o2: u1,
6459 Rn: Register.Encoded,
6460 decoded10: u5 = 0b0001,
6461 imm6: u6,
6462 decoded21: u8 = 0b11010000,
6463 S: bool,
6464 op: u1,
6465 sf: Register.GeneralSize,
6466 };
6467 };
6468
6469 /// Evaluate into flags
6470 pub const EvaluateIntoFlags = packed union {
6471 group: @This().Group,
6472
6473 pub const Group = packed struct {
6474 mask: Nzcv,
6475 o3: u1,
6476 Rn: Register.Encoded,
6477 decoded10: u4 = 0b0010,
6478 sz: enum(u1) {
6479 byte = 0b0,
6480 word = 0b1,
6481 },
6482 opcode2: u6,
6483 decoded21: u8 = 0b11010000,
6484 S: bool,
6485 op: u1,
6486 sf: Register.GeneralSize,
6487 };
6488 };
6489
6490 /// Conditional compare (register)
6491 pub const ConditionalCompareRegister = packed union {
6492 group: @This().Group,
6493 ccmn: Ccmn,
6494 ccmp: Ccmp,
6495
6496 pub const Group = packed struct {
6497 nzcv: Nzcv,
6498 o3: u1,
6499 Rn: Register.Encoded,
6500 o2: u1,
6501 decoded11: u1 = 0b0,
6502 cond: ConditionCode,
6503 Rm: Register.Encoded,
6504 decoded21: u8 = 0b11010010,
6505 S: bool,
6506 op: Op,
6507 sf: Register.GeneralSize,
6508 };
6509
6510 /// C6.2.49 CCMN (register)
6511 pub const Ccmn = packed struct {
6512 nzcv: Nzcv,
6513 o3: u1 = 0b0,
6514 Rn: Register.Encoded,
6515 o2: u1 = 0b0,
6516 decoded11: u1 = 0b0,
6517 cond: ConditionCode,
6518 Rm: Register.Encoded,
6519 decoded21: u8 = 0b11010010,
6520 S: bool = true,
6521 op: Op = .ccmn,
6522 sf: Register.GeneralSize,
6523 };
6524
6525 /// C6.2.51 CCMP (register)
6526 pub const Ccmp = packed struct {
6527 nzcv: Nzcv,
6528 o3: u1 = 0b0,
6529 Rn: Register.Encoded,
6530 o2: u1 = 0b0,
6531 decoded11: u1 = 0b0,
6532 cond: ConditionCode,
6533 Rm: Register.Encoded,
6534 decoded21: u8 = 0b11010010,
6535 S: bool = true,
6536 op: Op = .ccmp,
6537 sf: Register.GeneralSize,
6538 };
6539
6540 pub const Op = enum(u1) {
6541 ccmn = 0b0,
6542 ccmp = 0b1,
6543 };
6544 };
6545
6546 /// Conditional compare (immediate)
6547 pub const ConditionalCompareImmediate = packed union {
6548 group: @This().Group,
6549 ccmn: Ccmn,
6550 ccmp: Ccmp,
6551
6552 pub const Group = packed struct {
6553 nzcv: Nzcv,
6554 o3: u1,
6555 Rn: Register.Encoded,
6556 o2: u1,
6557 decoded11: u1 = 0b1,
6558 cond: ConditionCode,
6559 imm5: u5,
6560 decoded21: u8 = 0b11010010,
6561 S: bool,
6562 op: Op,
6563 sf: Register.GeneralSize,
6564 };
6565
6566 /// C6.2.48 CCMN (immediate)
6567 pub const Ccmn = packed struct {
6568 nzcv: Nzcv,
6569 o3: u1 = 0b0,
6570 Rn: Register.Encoded,
6571 o2: u1 = 0b0,
6572 decoded11: u1 = 0b1,
6573 cond: ConditionCode,
6574 imm5: u5,
6575 decoded21: u8 = 0b11010010,
6576 S: bool = true,
6577 op: Op = .ccmn,
6578 sf: Register.GeneralSize,
6579 };
6580
6581 /// C6.2.50 CCMP (immediate)
6582 pub const Ccmp = packed struct {
6583 nzcv: Nzcv,
6584 o3: u1 = 0b0,
6585 Rn: Register.Encoded,
6586 o2: u1 = 0b0,
6587 decoded11: u1 = 0b1,
6588 cond: ConditionCode,
6589 imm5: u5,
6590 decoded21: u8 = 0b11010010,
6591 S: bool = true,
6592 op: Op = .ccmp,
6593 sf: Register.GeneralSize,
6594 };
6595
6596 pub const Op = enum(u1) {
6597 ccmn = 0b0,
6598 ccmp = 0b1,
6599 };
6600 };
6601
6602 /// Conditional select
6603 pub const ConditionalSelect = packed union {
6604 group: @This().Group,
6605 csel: Csel,
6606 csinc: Csinc,
6607 csinv: Csinv,
6608 csneg: Csneg,
6609
6610 pub const Group = packed struct {
6611 Rd: Register.Encoded,
6612 Rn: Register.Encoded,
6613 op2: u2,
6614 cond: ConditionCode,
6615 Rm: Register.Encoded,
6616 decoded21: u8 = 0b11010100,
6617 S: bool,
6618 op: u1,
6619 sf: Register.GeneralSize,
6620 };
6621
6622 /// C6.2.103 CSEL
6623 pub const Csel = packed struct {
6624 Rd: Register.Encoded,
6625 Rn: Register.Encoded,
6626 op2: u2 = 0b00,
6627 cond: ConditionCode,
6628 Rm: Register.Encoded,
6629 decoded21: u8 = 0b11010100,
6630 S: bool = false,
6631 op: u1 = 0b0,
6632 sf: Register.GeneralSize,
6633 };
6634
6635 /// C6.2.106 CSINC
6636 pub const Csinc = packed struct {
6637 Rd: Register.Encoded,
6638 Rn: Register.Encoded,
6639 op2: u2 = 0b01,
6640 cond: ConditionCode,
6641 Rm: Register.Encoded,
6642 decoded21: u8 = 0b11010100,
6643 S: bool = false,
6644 op: u1 = 0b0,
6645 sf: Register.GeneralSize,
6646 };
6647
6648 /// C6.2.107 CSINV
6649 pub const Csinv = packed struct {
6650 Rd: Register.Encoded,
6651 Rn: Register.Encoded,
6652 op2: u2 = 0b00,
6653 cond: ConditionCode,
6654 Rm: Register.Encoded,
6655 decoded21: u8 = 0b11010100,
6656 S: bool = false,
6657 op: u1 = 0b1,
6658 sf: Register.GeneralSize,
6659 };
6660
6661 /// C6.2.108 CSNEG
6662 pub const Csneg = packed struct {
6663 Rd: Register.Encoded,
6664 Rn: Register.Encoded,
6665 op2: u2 = 0b01,
6666 cond: ConditionCode,
6667 Rm: Register.Encoded,
6668 decoded21: u8 = 0b11010100,
6669 S: bool = false,
6670 op: u1 = 0b1,
6671 sf: Register.GeneralSize,
6672 };
6673
6674 pub const Decoded = union(enum) {
6675 unallocated,
6676 csel: Csel,
6677 csinc: Csinc,
6678 csinv: Csinv,
6679 csneg: Csneg,
6680 };
6681 pub fn decode(inst: @This()) @This().Decoded {
6682 return switch (inst.group.S) {
6683 true => .unallocated,
6684 false => switch (inst.group.op) {
6685 0b0 => switch (inst.group.op2) {
6686 0b10...0b11 => .unallocated,
6687 0b00 => .{ .csel = inst.csel },
6688 0b01 => .{ .csinc = inst.csinc },
6689 },
6690 0b1 => switch (inst.group.op2) {
6691 0b10...0b11 => .unallocated,
6692 0b00 => .{ .csinv = inst.csinv },
6693 0b01 => .{ .csneg = inst.csneg },
6694 },
6695 },
6696 };
6697 }
6698 };
6699
6700 /// Data-processing (3 source)
6701 pub const DataProcessingThreeSource = packed union {
6702 group: @This().Group,
6703 madd: Madd,
6704 msub: Msub,
6705 smaddl: Smaddl,
6706 smsubl: Smsubl,
6707 smulh: Smulh,
6708 umaddl: Umaddl,
6709 umsubl: Umsubl,
6710 umulh: Umulh,
6711
6712 pub const Group = packed struct {
6713 Rd: Register.Encoded,
6714 Rn: Register.Encoded,
6715 Ra: Register.Encoded,
6716 o0: AddSubtractOp,
6717 Rm: Register.Encoded,
6718 op31: u3,
6719 decoded24: u5 = 0b11011,
6720 op54: u2,
6721 sf: Register.GeneralSize,
6722 };
6723
6724 /// C6.2.218 MADD
6725 pub const Madd = packed struct {
6726 Rd: Register.Encoded,
6727 Rn: Register.Encoded,
6728 Ra: Register.Encoded,
6729 o0: AddSubtractOp = .add,
6730 Rm: Register.Encoded,
6731 op31: u3 = 0b000,
6732 decoded24: u5 = 0b11011,
6733 op54: u2 = 0b00,
6734 sf: Register.GeneralSize,
6735 };
6736
6737 /// C6.2.231 MSUB
6738 pub const Msub = packed struct {
6739 Rd: Register.Encoded,
6740 Rn: Register.Encoded,
6741 Ra: Register.Encoded,
6742 o0: AddSubtractOp = .sub,
6743 Rm: Register.Encoded,
6744 op31: u3 = 0b000,
6745 decoded24: u5 = 0b11011,
6746 op54: u2 = 0b00,
6747 sf: Register.GeneralSize,
6748 };
6749
6750 /// C6.2.282 SMADDL
6751 pub const Smaddl = packed struct {
6752 Rd: Register.Encoded,
6753 Rn: Register.Encoded,
6754 Ra: Register.Encoded,
6755 o0: AddSubtractOp = .add,
6756 Rm: Register.Encoded,
6757 op21: u2 = 0b01,
6758 U: std.builtin.Signedness = .signed,
6759 decoded24: u5 = 0b11011,
6760 op54: u2 = 0b00,
6761 sf: Register.GeneralSize = .doubleword,
6762 };
6763
6764 /// C6.2.287 SMSUBL
6765 pub const Smsubl = packed struct {
6766 Rd: Register.Encoded,
6767 Rn: Register.Encoded,
6768 Ra: Register.Encoded,
6769 o0: AddSubtractOp = .sub,
6770 Rm: Register.Encoded,
6771 op21: u2 = 0b01,
6772 U: std.builtin.Signedness = .signed,
6773 decoded24: u5 = 0b11011,
6774 op54: u2 = 0b00,
6775 sf: Register.GeneralSize = .doubleword,
6776 };
6777
6778 /// C6.2.288 SMULH
6779 pub const Smulh = packed struct {
6780 Rd: Register.Encoded,
6781 Rn: Register.Encoded,
6782 Ra: Register.Encoded = Register.Alias.zr.encode(.{}),
6783 o0: AddSubtractOp = .add,
6784 Rm: Register.Encoded,
6785 op21: u2 = 0b10,
6786 U: std.builtin.Signedness = .signed,
6787 decoded24: u5 = 0b11011,
6788 op54: u2 = 0b00,
6789 sf: Register.GeneralSize = .doubleword,
6790 };
6791
6792 /// C6.2.389 UMADDL
6793 pub const Umaddl = packed struct {
6794 Rd: Register.Encoded,
6795 Rn: Register.Encoded,
6796 Ra: Register.Encoded,
6797 o0: AddSubtractOp = .add,
6798 Rm: Register.Encoded,
6799 op21: u2 = 0b01,
6800 U: std.builtin.Signedness = .unsigned,
6801 decoded24: u5 = 0b11011,
6802 op54: u2 = 0b00,
6803 sf: Register.GeneralSize = .doubleword,
6804 };
6805
6806 /// C6.2.391 UMSUBL
6807 pub const Umsubl = packed struct {
6808 Rd: Register.Encoded,
6809 Rn: Register.Encoded,
6810 Ra: Register.Encoded,
6811 o0: AddSubtractOp = .sub,
6812 Rm: Register.Encoded,
6813 op21: u2 = 0b01,
6814 U: std.builtin.Signedness = .unsigned,
6815 decoded24: u5 = 0b11011,
6816 op54: u2 = 0b00,
6817 sf: Register.GeneralSize = .doubleword,
6818 };
6819
6820 /// C6.2.392 UMULH
6821 pub const Umulh = packed struct {
6822 Rd: Register.Encoded,
6823 Rn: Register.Encoded,
6824 Ra: Register.Encoded = Register.Alias.zr.encode(.{}),
6825 o0: AddSubtractOp = .add,
6826 Rm: Register.Encoded,
6827 op21: u2 = 0b10,
6828 U: std.builtin.Signedness = .unsigned,
6829 decoded24: u5 = 0b11011,
6830 op54: u2 = 0b00,
6831 sf: Register.GeneralSize = .doubleword,
6832 };
6833
6834 pub const Decoded = union(enum) {
6835 unallocated,
6836 madd: Madd,
6837 msub: Msub,
6838 smaddl: Smaddl,
6839 smsubl: Smsubl,
6840 smulh: Smulh,
6841 umaddl: Umaddl,
6842 umsubl: Umsubl,
6843 umulh: Umulh,
6844 };
6845 pub fn decode(inst: @This()) @This().Decoded {
6846 return switch (inst.group.op54) {
6847 0b01, 0b10...0b11 => .unallocated,
6848 0b00 => switch (inst.group.op31) {
6849 0b011, 0b100, 0b111 => .unallocated,
6850 0b000 => switch (inst.group.o0) {
6851 .add => .{ .madd = inst.madd },
6852 .sub => .{ .msub = inst.msub },
6853 },
6854 0b001 => switch (inst.group.sf) {
6855 .word => .unallocated,
6856 .doubleword => switch (inst.group.o0) {
6857 .add => .{ .smaddl = inst.smaddl },
6858 .sub => .{ .smsubl = inst.smsubl },
6859 },
6860 },
6861 0b010 => switch (inst.group.sf) {
6862 .word => .unallocated,
6863 .doubleword => switch (inst.group.o0) {
6864 .add => .{ .smulh = inst.smulh },
6865 .sub => .unallocated,
6866 },
6867 },
6868 0b101 => switch (inst.group.sf) {
6869 .word => .unallocated,
6870 .doubleword => switch (inst.group.o0) {
6871 .add => .{ .umaddl = inst.umaddl },
6872 .sub => .{ .umsubl = inst.umsubl },
6873 },
6874 },
6875 0b110 => switch (inst.group.sf) {
6876 .word => .unallocated,
6877 .doubleword => switch (inst.group.o0) {
6878 .add => .{ .umulh = inst.umulh },
6879 .sub => .unallocated,
6880 },
6881 },
6882 },
6883 };
6884 }
6885 };
6886
6887 pub const Shift = union(enum(u2)) {
6888 lsl: Amount = 0b00,
6889 lsr: Amount = 0b01,
6890 asr: Amount = 0b10,
6891 ror: Amount = 0b11,
6892
6893 pub const Op = @typeInfo(Shift).@"union".tag_type.?;
6894 pub const Amount = u6;
6895 pub const none: Shift = .{ .lsl = 0 };
6896 };
6897
6898 pub const Decoded = union(enum) {
6899 unallocated,
6900 data_processing_two_source: DataProcessingTwoSource,
6901 data_processing_one_source: DataProcessingOneSource,
6902 logical_shifted_register: LogicalShiftedRegister,
6903 add_subtract_shifted_register: AddSubtractShiftedRegister,
6904 add_subtract_extended_register: AddSubtractExtendedRegister,
6905 add_subtract_with_carry: AddSubtractWithCarry,
6906 rotate_right_into_flags: RotateRightIntoFlags,
6907 evaluate_into_flags: EvaluateIntoFlags,
6908 conditional_compare_register: ConditionalCompareRegister,
6909 conditional_compare_immediate: ConditionalCompareImmediate,
6910 conditional_select: ConditionalSelect,
6911 data_processing_three_source: DataProcessingThreeSource,
6912 };
6913 pub fn decode(inst: @This()) @This().Decoded {
6914 return switch (inst.group.op1) {
6915 0b0 => switch (@as(u1, @truncate(inst.group.op2 >> 3))) {
6916 0b0 => .{ .logical_shifted_register = inst.logical_shifted_register },
6917 0b1 => switch (@as(u1, @truncate(inst.group.op2 >> 0))) {
6918 0b0 => .{ .add_subtract_shifted_register = inst.add_subtract_shifted_register },
6919 0b1 => .{ .add_subtract_extended_register = inst.add_subtract_extended_register },
6920 },
6921 },
6922 0b1 => switch (inst.group.op2) {
6923 0b0000 => switch (inst.group.op3) {
6924 0b000000 => .{ .add_subtract_with_carry = inst.add_subtract_with_carry },
6925 0b000001, 0b100001 => .{ .rotate_right_into_flags = inst.rotate_right_into_flags },
6926 0b000010, 0b010010, 0b100010, 0b110010 => .{ .evaluate_into_flags = inst.evaluate_into_flags },
6927 else => .unallocated,
6928 },
6929 0b0010 => switch (@as(u1, @truncate(inst.group.op3 >> 1))) {
6930 0b0 => .{ .conditional_compare_register = inst.conditional_compare_register },
6931 0b1 => .{ .conditional_compare_immediate = inst.conditional_compare_immediate },
6932 },
6933 0b0100 => .{ .conditional_select = inst.conditional_select },
6934 0b0110 => switch (inst.group.op0) {
6935 0b0 => .{ .data_processing_two_source = inst.data_processing_two_source },
6936 0b1 => .{ .data_processing_one_source = inst.data_processing_one_source },
6937 },
6938 0b1000...0b1111 => .{ .data_processing_three_source = inst.data_processing_three_source },
6939 else => .unallocated,
6940 },
6941 };
6942 }
6943 };
6944
6945 /// C4.1.90 Data Processing -- Scalar Floating-Point and Advanced SIMD
6946 pub const DataProcessingVector = packed union {
6947 group: @This().Group,
6948 simd_scalar_copy: SimdScalarCopy,
6949 simd_scalar_two_register_miscellaneous_fp16: SimdScalarTwoRegisterMiscellaneousFp16,
6950 simd_scalar_two_register_miscellaneous: SimdScalarTwoRegisterMiscellaneous,
6951 simd_scalar_pairwise: SimdScalarPairwise,
6952 simd_copy: SimdCopy,
6953 simd_two_register_miscellaneous_fp16: SimdTwoRegisterMiscellaneousFp16,
6954 simd_two_register_miscellaneous: SimdTwoRegisterMiscellaneous,
6955 simd_across_lanes: SimdAcrossLanes,
6956 simd_three_same: SimdThreeSame,
6957 simd_modified_immediate: SimdModifiedImmediate,
6958 convert_float_fixed: ConvertFloatFixed,
6959 convert_float_integer: ConvertFloatInteger,
6960 float_data_processing_one_source: FloatDataProcessingOneSource,
6961 float_compare: FloatCompare,
6962 float_immediate: FloatImmediate,
6963 float_conditional_compare: FloatConditionalCompare,
6964 float_data_processing_two_source: FloatDataProcessingTwoSource,
6965 float_conditional_select: FloatConditionalSelect,
6966 float_data_processing_three_source: FloatDataProcessingThreeSource,
6967
6968 /// Table C4-91 Encoding table for the Data Processing -- Scalar Floating-Point and Advanced SIMD group
6969 pub const Group = packed struct {
6970 encoded0: u10,
6971 op3: u9,
6972 op2: u4,
6973 op1: u2,
6974 decoded25: u3 = 0b111,
6975 op0: u4,
6976 };
6977
6978 /// Advanced SIMD scalar copy
6979 pub const SimdScalarCopy = packed union {
6980 group: @This().Group,
6981 dup: Dup,
6982
6983 pub const Group = packed struct {
6984 Rd: Register.Encoded,
6985 Rn: Register.Encoded,
6986 decoded10: u1 = 0b1,
6987 imm4: u4,
6988 decoded15: u1 = 0b0,
6989 imm5: u5,
6990 decoded21: u8 = 0b11110000,
6991 op: u1,
6992 decoded30: u2 = 0b01,
6993 };
6994
6995 /// C7.2.39 DUP (element)
6996 pub const Dup = packed struct {
6997 Rd: Register.Encoded,
6998 Rn: Register.Encoded,
6999 decoded10: u1 = 0b1,
7000 imm4: u4 = 0b0000,
7001 decoded15: u1 = 0b0,
7002 imm5: u5,
7003 decoded21: u8 = 0b11110000,
7004 op: u1 = 0b0,
7005 decoded30: u2 = 0b01,
7006 };
7007
7008 pub const Decoded = union(enum) {
7009 unallocated,
7010 dup: Dup,
7011 };
7012 pub fn decode(inst: @This()) @This().Decoded {
7013 return switch (inst.group.op) {
7014 0b0 => switch (inst.group.imm4) {
7015 else => .unallocated,
7016 0b0000 => .{ .dup = inst.dup },
7017 },
7018 0b1 => .unallocated,
7019 };
7020 }
7021 };
7022
7023 /// Advanced SIMD scalar two-register miscellaneous FP16
7024 pub const SimdScalarTwoRegisterMiscellaneousFp16 = packed union {
7025 group: @This().Group,
7026 fcvtns: Fcvtns,
7027 fcvtms: Fcvtms,
7028 fcvtas: Fcvtas,
7029 scvtf: Scvtf,
7030 fcmgt: Fcmgt,
7031 fcmeq: Fcmeq,
7032 fcmlt: Fcmlt,
7033 fcvtps: Fcvtps,
7034 fcvtzs: Fcvtzs,
7035 frecpe: Frecpe,
7036 frecpx: Frecpx,
7037 fcvtnu: Fcvtnu,
7038 fcvtmu: Fcvtmu,
7039 fcvtau: Fcvtau,
7040 ucvtf: Ucvtf,
7041 fcmge: Fcmge,
7042 fcmle: Fcmle,
7043 fcvtpu: Fcvtpu,
7044 fcvtzu: Fcvtzu,
7045 frsqrte: Frsqrte,
7046
7047 pub const Group = packed struct {
7048 Rd: Register.Encoded,
7049 Rn: Register.Encoded,
7050 decoded10: u2 = 0b10,
7051 opcode: u5,
7052 decoded17: u6 = 0b111100,
7053 a: u1,
7054 decoded24: u5 = 0b11110,
7055 U: std.builtin.Signedness,
7056 decoded30: u2 = 0b01,
7057 };
7058
7059 /// C7.2.80 FCVTNS (vector)
7060 pub const Fcvtns = packed struct {
7061 Rd: Register.Encoded,
7062 Rn: Register.Encoded,
7063 decoded10: u2 = 0b10,
7064 opcode: u5 = 0b11010,
7065 decoded17: u6 = 0b111100,
7066 o2: u1 = 0b0,
7067 decoded24: u5 = 0b11110,
7068 U: std.builtin.Signedness = .signed,
7069 decoded30: u2 = 0b01,
7070 };
7071
7072 /// C7.2.75 FCVTMS (vector)
7073 pub const Fcvtms = packed struct {
7074 Rd: Register.Encoded,
7075 Rn: Register.Encoded,
7076 decoded10: u2 = 0b10,
7077 opcode: u5 = 0b11011,
7078 decoded17: u6 = 0b111100,
7079 o2: u1 = 0b0,
7080 decoded24: u5 = 0b11110,
7081 U: std.builtin.Signedness = .signed,
7082 decoded30: u2 = 0b01,
7083 };
7084
7085 /// C7.2.70 FCVTAS (vector)
7086 pub const Fcvtas = packed struct {
7087 Rd: Register.Encoded,
7088 Rn: Register.Encoded,
7089 decoded10: u2 = 0b10,
7090 opcode: u5 = 0b11100,
7091 decoded17: u6 = 0b111100,
7092 o2: u1 = 0b0,
7093 decoded24: u5 = 0b11110,
7094 U: std.builtin.Signedness = .signed,
7095 decoded30: u2 = 0b01,
7096 };
7097
7098 /// C7.2.234 SCVTF (vector, integer)
7099 pub const Scvtf = packed struct {
7100 Rd: Register.Encoded,
7101 Rn: Register.Encoded,
7102 decoded10: u2 = 0b10,
7103 opcode: u5 = 0b11101,
7104 decoded17: u6 = 0b111100,
7105 o2: u1 = 0b0,
7106 decoded24: u5 = 0b11110,
7107 U: std.builtin.Signedness = .signed,
7108 decoded30: u2 = 0b01,
7109 };
7110
7111 /// C7.2.61 FCMGT (zero)
7112 pub const Fcmgt = packed struct {
7113 Rd: Register.Encoded,
7114 Rn: Register.Encoded,
7115 decoded10: u2 = 0b10,
7116 opcode: u5 = 0b01100,
7117 decoded17: u6 = 0b111100,
7118 o2: u1 = 0b1,
7119 decoded24: u5 = 0b11110,
7120 U: std.builtin.Signedness = .signed,
7121 decoded30: u2 = 0b01,
7122 };
7123
7124 /// C7.2.57 FCMEQ (zero)
7125 pub const Fcmeq = packed struct {
7126 Rd: Register.Encoded,
7127 Rn: Register.Encoded,
7128 decoded10: u2 = 0b10,
7129 opcode: u5 = 0b01101,
7130 decoded17: u6 = 0b111100,
7131 o2: u1 = 0b1,
7132 decoded24: u5 = 0b11110,
7133 U: std.builtin.Signedness = .signed,
7134 decoded30: u2 = 0b01,
7135 };
7136
7137 /// C7.2.65 FCMLT (zero)
7138 pub const Fcmlt = packed struct {
7139 Rd: Register.Encoded,
7140 Rn: Register.Encoded,
7141 decoded10: u2 = 0b10,
7142 opcode: u5 = 0b01110,
7143 decoded17: u6 = 0b111100,
7144 o2: u1 = 0b1,
7145 decoded24: u5 = 0b11110,
7146 U: std.builtin.Signedness = .signed,
7147 decoded30: u2 = 0b01,
7148 };
7149
7150 /// C7.2.84 FCVTPS (vector)
7151 pub const Fcvtps = packed struct {
7152 Rd: Register.Encoded,
7153 Rn: Register.Encoded,
7154 decoded10: u2 = 0b10,
7155 opcode: u5 = 0b11010,
7156 decoded17: u6 = 0b111100,
7157 o2: u1 = 0b1,
7158 decoded24: u5 = 0b11110,
7159 U: std.builtin.Signedness = .signed,
7160 decoded30: u2 = 0b01,
7161 };
7162
7163 /// C7.2.90 FCVTZS (vector, integer)
7164 pub const Fcvtzs = packed struct {
7165 Rd: Register.Encoded,
7166 Rn: Register.Encoded,
7167 decoded10: u2 = 0b10,
7168 opcode: u5 = 0b11011,
7169 decoded17: u6 = 0b111100,
7170 o2: u1 = 0b1,
7171 decoded24: u5 = 0b11110,
7172 U: std.builtin.Signedness = .signed,
7173 decoded30: u2 = 0b01,
7174 };
7175
7176 /// C7.2.144 FRECPE
7177 pub const Frecpe = packed struct {
7178 Rd: Register.Encoded,
7179 Rn: Register.Encoded,
7180 decoded10: u2 = 0b10,
7181 opcode: u5 = 0b11101,
7182 decoded17: u6 = 0b111100,
7183 o2: u1 = 0b1,
7184 decoded24: u5 = 0b11110,
7185 U: std.builtin.Signedness = .signed,
7186 decoded30: u2 = 0b01,
7187 };
7188
7189 /// C7.2.146 FRECPX
7190 pub const Frecpx = packed struct {
7191 Rd: Register.Encoded,
7192 Rn: Register.Encoded,
7193 decoded10: u2 = 0b10,
7194 opcode: u5 = 0b11111,
7195 decoded17: u6 = 0b111100,
7196 o2: u1 = 0b1,
7197 decoded24: u5 = 0b11110,
7198 U: std.builtin.Signedness = .signed,
7199 decoded30: u2 = 0b01,
7200 };
7201
7202 /// C7.2.82 FCVTNU (vector)
7203 pub const Fcvtnu = packed struct {
7204 Rd: Register.Encoded,
7205 Rn: Register.Encoded,
7206 decoded10: u2 = 0b10,
7207 opcode: u5 = 0b11010,
7208 decoded17: u6 = 0b111100,
7209 o2: u1 = 0b0,
7210 decoded24: u5 = 0b11110,
7211 U: std.builtin.Signedness = .unsigned,
7212 decoded30: u2 = 0b01,
7213 };
7214
7215 /// C7.2.77 FCVTMU (vector)
7216 pub const Fcvtmu = packed struct {
7217 Rd: Register.Encoded,
7218 Rn: Register.Encoded,
7219 decoded10: u2 = 0b10,
7220 opcode: u5 = 0b11011,
7221 decoded17: u6 = 0b111100,
7222 o2: u1 = 0b0,
7223 decoded24: u5 = 0b11110,
7224 U: std.builtin.Signedness = .unsigned,
7225 decoded30: u2 = 0b01,
7226 };
7227
7228 /// C7.2.72 FCVTAU (vector)
7229 pub const Fcvtau = packed struct {
7230 Rd: Register.Encoded,
7231 Rn: Register.Encoded,
7232 decoded10: u2 = 0b10,
7233 opcode: u5 = 0b11100,
7234 decoded17: u6 = 0b111100,
7235 o2: u1 = 0b0,
7236 decoded24: u5 = 0b11110,
7237 U: std.builtin.Signedness = .unsigned,
7238 decoded30: u2 = 0b01,
7239 };
7240
7241 /// C7.2.353 UCVTF (vector, integer)
7242 pub const Ucvtf = packed struct {
7243 Rd: Register.Encoded,
7244 Rn: Register.Encoded,
7245 decoded10: u2 = 0b10,
7246 opcode: u5 = 0b11101,
7247 decoded17: u6 = 0b111100,
7248 o2: u1 = 0b0,
7249 decoded24: u5 = 0b11110,
7250 U: std.builtin.Signedness = .unsigned,
7251 decoded30: u2 = 0b01,
7252 };
7253
7254 /// C7.2.59 FCMGE (zero)
7255 pub const Fcmge = packed struct {
7256 Rd: Register.Encoded,
7257 Rn: Register.Encoded,
7258 decoded10: u2 = 0b10,
7259 opcode: u5 = 0b01100,
7260 decoded17: u6 = 0b111100,
7261 o2: u1 = 0b1,
7262 decoded24: u5 = 0b11110,
7263 U: std.builtin.Signedness = .unsigned,
7264 decoded30: u2 = 0b01,
7265 };
7266
7267 /// C7.2.64 FCMLE (zero)
7268 pub const Fcmle = packed struct {
7269 Rd: Register.Encoded,
7270 Rn: Register.Encoded,
7271 decoded10: u2 = 0b10,
7272 opcode: u5 = 0b01101,
7273 decoded17: u6 = 0b111100,
7274 o2: u1 = 0b1,
7275 decoded24: u5 = 0b11110,
7276 U: std.builtin.Signedness = .unsigned,
7277 decoded30: u2 = 0b01,
7278 };
7279
7280 /// C7.2.86 FCVTPU (vector)
7281 pub const Fcvtpu = packed struct {
7282 Rd: Register.Encoded,
7283 Rn: Register.Encoded,
7284 decoded10: u2 = 0b10,
7285 opcode: u5 = 0b11010,
7286 decoded17: u6 = 0b111100,
7287 o2: u1 = 0b1,
7288 decoded24: u5 = 0b11110,
7289 U: std.builtin.Signedness = .unsigned,
7290 decoded30: u2 = 0b01,
7291 };
7292
7293 /// C7.2.94 FCVTZU (vector, integer)
7294 pub const Fcvtzu = packed struct {
7295 Rd: Register.Encoded,
7296 Rn: Register.Encoded,
7297 decoded10: u2 = 0b10,
7298 opcode: u5 = 0b11011,
7299 decoded17: u6 = 0b111100,
7300 o2: u1 = 0b1,
7301 decoded24: u5 = 0b11110,
7302 U: std.builtin.Signedness = .unsigned,
7303 decoded30: u2 = 0b01,
7304 };
7305
7306 /// C7.2.169 FRSQRTE
7307 pub const Frsqrte = packed struct {
7308 Rd: Register.Encoded,
7309 Rn: Register.Encoded,
7310 decoded10: u2 = 0b10,
7311 opcode: u5 = 0b11101,
7312 decoded17: u6 = 0b111100,
7313 o2: u1 = 0b1,
7314 decoded24: u5 = 0b11110,
7315 U: std.builtin.Signedness = .unsigned,
7316 decoded30: u2 = 0b01,
7317 };
7318
7319 pub const Decoded = union(enum) {
7320 unallocated,
7321 fcvtns: Fcvtns,
7322 fcvtms: Fcvtms,
7323 fcvtas: Fcvtas,
7324 scvtf: Scvtf,
7325 fcmgt: Fcmgt,
7326 fcmeq: Fcmeq,
7327 fcmlt: Fcmlt,
7328 fcvtps: Fcvtps,
7329 fcvtzs: Fcvtzs,
7330 frecpe: Frecpe,
7331 frecpx: Frecpx,
7332 fcvtnu: Fcvtnu,
7333 fcvtmu: Fcvtmu,
7334 fcvtau: Fcvtau,
7335 ucvtf: Ucvtf,
7336 fcmge: Fcmge,
7337 fcmle: Fcmle,
7338 fcvtpu: Fcvtpu,
7339 fcvtzu: Fcvtzu,
7340 frsqrte: Frsqrte,
7341 };
7342 pub fn decode(inst: @This()) @This().Decoded {
7343 return switch (inst.group.U) {
7344 .signed => switch (inst.group.a) {
7345 0b0 => switch (inst.group.opcode) {
7346 else => .unallocated,
7347 0b11010 => .{ .fcvtns = inst.fcvtns },
7348 0b11011 => .{ .fcvtms = inst.fcvtms },
7349 0b11100 => .{ .fcvtas = inst.fcvtas },
7350 0b11101 => .{ .scvtf = inst.scvtf },
7351 },
7352 0b1 => switch (inst.group.opcode) {
7353 else => .unallocated,
7354 0b01100 => .{ .fcmgt = inst.fcmgt },
7355 0b01101 => .{ .fcmeq = inst.fcmeq },
7356 0b01110 => .{ .fcmlt = inst.fcmlt },
7357 0b11010 => .{ .fcvtps = inst.fcvtps },
7358 0b11011 => .{ .fcvtzs = inst.fcvtzs },
7359 0b11101 => .{ .frecpe = inst.frecpe },
7360 0b11111 => .{ .frecpx = inst.frecpx },
7361 },
7362 },
7363 .unsigned => switch (inst.group.a) {
7364 0b0 => switch (inst.group.opcode) {
7365 else => .unallocated,
7366 0b11010 => .{ .fcvtnu = inst.fcvtnu },
7367 0b11011 => .{ .fcvtmu = inst.fcvtmu },
7368 0b11100 => .{ .fcvtau = inst.fcvtau },
7369 0b11101 => .{ .ucvtf = inst.ucvtf },
7370 },
7371 0b1 => switch (inst.group.opcode) {
7372 else => .unallocated,
7373 0b01100 => .{ .fcmge = inst.fcmge },
7374 0b01101 => .{ .fcmle = inst.fcmle },
7375 0b11010 => .{ .fcvtpu = inst.fcvtpu },
7376 0b11011 => .{ .fcvtzu = inst.fcvtzu },
7377 0b11101 => .{ .frsqrte = inst.frsqrte },
7378 },
7379 },
7380 };
7381 }
7382 };
7383
7384 /// Advanced SIMD scalar two-register miscellaneous
7385 pub const SimdScalarTwoRegisterMiscellaneous = packed union {
7386 group: @This().Group,
7387 suqadd: Suqadd,
7388 sqabs: Sqabs,
7389 cmgt: Cmgt,
7390 cmeq: Cmeq,
7391 cmlt: Cmlt,
7392 abs: Abs,
7393 sqxtn: Sqxtn,
7394 fcvtns: Fcvtns,
7395 fcvtms: Fcvtms,
7396 fcvtas: Fcvtas,
7397 scvtf: Scvtf,
7398 fcmgt: Fcmgt,
7399 fcmeq: Fcmeq,
7400 fcmlt: Fcmlt,
7401 fcvtps: Fcvtps,
7402 fcvtzs: Fcvtzs,
7403 frecpe: Frecpe,
7404 frecpx: Frecpx,
7405 usqadd: Usqadd,
7406 sqneg: Sqneg,
7407 cmge: Cmge,
7408 cmle: Cmle,
7409 neg: Neg,
7410 sqxtun: Sqxtun,
7411 uqxtn: Uqxtn,
7412 fcvtxn: Fcvtxn,
7413 fcvtnu: Fcvtnu,
7414 fcvtmu: Fcvtmu,
7415 fcvtau: Fcvtau,
7416 ucvtf: Ucvtf,
7417 fcmge: Fcmge,
7418 fcmle: Fcmle,
7419 fcvtpu: Fcvtpu,
7420 fcvtzu: Fcvtzu,
7421 frsqrte: Frsqrte,
7422
7423 pub const Group = packed struct {
7424 Rd: Register.Encoded,
7425 Rn: Register.Encoded,
7426 decoded10: u2 = 0b10,
7427 opcode: u5,
7428 decoded17: u5 = 0b10000,
7429 size: Size,
7430 decoded24: u5 = 0b11110,
7431 U: std.builtin.Signedness,
7432 decoded30: u2 = 0b01,
7433 };
7434
7435 /// C7.2.337 SUQADD
7436 pub const Suqadd = packed struct {
7437 Rd: Register.Encoded,
7438 Rn: Register.Encoded,
7439 decoded10: u2 = 0b10,
7440 opcode: u5 = 0b00011,
7441 decoded17: u5 = 0b10000,
7442 size: Size,
7443 decoded24: u5 = 0b11110,
7444 U: std.builtin.Signedness = .signed,
7445 decoded30: u2 = 0b01,
7446 };
7447
7448 /// C7.2.282 SQABS
7449 pub const Sqabs = packed struct {
7450 Rd: Register.Encoded,
7451 Rn: Register.Encoded,
7452 decoded10: u2 = 0b10,
7453 opcode: u5 = 0b00111,
7454 decoded17: u5 = 0b10000,
7455 size: Size,
7456 decoded24: u5 = 0b11110,
7457 U: std.builtin.Signedness = .signed,
7458 decoded30: u2 = 0b01,
7459 };
7460
7461 /// C7.2.32 CMGT (zero)
7462 pub const Cmgt = packed struct {
7463 Rd: Register.Encoded,
7464 Rn: Register.Encoded,
7465 decoded10: u2 = 0b10,
7466 opcode: u5 = 0b01000,
7467 decoded17: u5 = 0b10000,
7468 size: Size,
7469 decoded24: u5 = 0b11110,
7470 U: std.builtin.Signedness = .signed,
7471 decoded30: u2 = 0b01,
7472 };
7473
7474 /// C7.2.28 CMEQ (zero)
7475 pub const Cmeq = packed struct {
7476 Rd: Register.Encoded,
7477 Rn: Register.Encoded,
7478 decoded10: u2 = 0b10,
7479 opcode: u5 = 0b01001,
7480 decoded17: u5 = 0b10000,
7481 size: Size,
7482 decoded24: u5 = 0b11110,
7483 U: std.builtin.Signedness = .signed,
7484 decoded30: u2 = 0b01,
7485 };
7486
7487 /// C7.2.36 CMLT (zero)
7488 pub const Cmlt = packed struct {
7489 Rd: Register.Encoded,
7490 Rn: Register.Encoded,
7491 decoded10: u2 = 0b10,
7492 opcode: u5 = 0b01010,
7493 decoded17: u5 = 0b10000,
7494 size: Size,
7495 decoded24: u5 = 0b11110,
7496 U: std.builtin.Signedness = .signed,
7497 decoded30: u2 = 0b01,
7498 };
7499
7500 /// C7.2.1 ABS
7501 pub const Abs = packed struct {
7502 Rd: Register.Encoded,
7503 Rn: Register.Encoded,
7504 decoded10: u2 = 0b10,
7505 opcode: u5 = 0b01011,
7506 decoded17: u5 = 0b10000,
7507 size: Size,
7508 decoded24: u5 = 0b11110,
7509 U: std.builtin.Signedness = .signed,
7510 decoded30: u2 = 0b01,
7511 };
7512
7513 /// C7.2.308 SQXTN
7514 pub const Sqxtn = packed struct {
7515 Rd: Register.Encoded,
7516 Rn: Register.Encoded,
7517 decoded10: u2 = 0b10,
7518 opcode: u5 = 0b10100,
7519 decoded17: u5 = 0b10000,
7520 size: Size,
7521 decoded24: u5 = 0b11110,
7522 U: std.builtin.Signedness = .signed,
7523 decoded30: u2 = 0b01,
7524 };
7525
7526 /// C7.2.80 FCVTNS (vector)
7527 pub const Fcvtns = packed struct {
7528 Rd: Register.Encoded,
7529 Rn: Register.Encoded,
7530 decoded10: u2 = 0b10,
7531 opcode: u5 = 0b11010,
7532 decoded17: u5 = 0b10000,
7533 sz: Sz,
7534 o2: u1 = 0b0,
7535 decoded24: u5 = 0b11110,
7536 U: std.builtin.Signedness = .signed,
7537 decoded30: u2 = 0b01,
7538 };
7539
7540 /// C7.2.75 FCVTMS (vector)
7541 pub const Fcvtms = packed struct {
7542 Rd: Register.Encoded,
7543 Rn: Register.Encoded,
7544 decoded10: u2 = 0b10,
7545 opcode: u5 = 0b11011,
7546 decoded17: u5 = 0b10000,
7547 sz: Sz,
7548 o2: u1 = 0b0,
7549 decoded24: u5 = 0b11110,
7550 U: std.builtin.Signedness = .signed,
7551 decoded30: u2 = 0b01,
7552 };
7553
7554 /// C7.2.70 FCVTAS (vector)
7555 pub const Fcvtas = packed struct {
7556 Rd: Register.Encoded,
7557 Rn: Register.Encoded,
7558 decoded10: u2 = 0b10,
7559 opcode: u5 = 0b11100,
7560 decoded17: u5 = 0b10000,
7561 sz: Sz,
7562 o2: u1 = 0b0,
7563 decoded24: u5 = 0b11110,
7564 U: std.builtin.Signedness = .signed,
7565 decoded30: u2 = 0b01,
7566 };
7567
7568 /// C7.2.234 SCVTF (vector, integer)
7569 pub const Scvtf = packed struct {
7570 Rd: Register.Encoded,
7571 Rn: Register.Encoded,
7572 decoded10: u2 = 0b10,
7573 opcode: u5 = 0b11101,
7574 decoded17: u5 = 0b10000,
7575 sz: Sz,
7576 o2: u1 = 0b0,
7577 decoded24: u5 = 0b11110,
7578 U: std.builtin.Signedness = .signed,
7579 decoded30: u2 = 0b01,
7580 };
7581
7582 /// C7.2.61 FCMGT (zero)
7583 pub const Fcmgt = packed struct {
7584 Rd: Register.Encoded,
7585 Rn: Register.Encoded,
7586 decoded10: u2 = 0b10,
7587 opcode: u5 = 0b01100,
7588 decoded17: u5 = 0b10000,
7589 sz: Sz,
7590 o2: u1 = 0b1,
7591 decoded24: u5 = 0b11110,
7592 U: std.builtin.Signedness = .signed,
7593 decoded30: u2 = 0b01,
7594 };
7595
7596 /// C7.2.57 FCMEQ (zero)
7597 pub const Fcmeq = packed struct {
7598 Rd: Register.Encoded,
7599 Rn: Register.Encoded,
7600 decoded10: u2 = 0b10,
7601 opcode: u5 = 0b01101,
7602 decoded17: u5 = 0b10000,
7603 sz: Sz,
7604 o2: u1 = 0b1,
7605 decoded24: u5 = 0b11110,
7606 U: std.builtin.Signedness = .signed,
7607 decoded30: u2 = 0b01,
7608 };
7609
7610 /// C7.2.65 FCMLT (zero)
7611 pub const Fcmlt = packed struct {
7612 Rd: Register.Encoded,
7613 Rn: Register.Encoded,
7614 decoded10: u2 = 0b10,
7615 opcode: u5 = 0b01110,
7616 decoded17: u5 = 0b10000,
7617 sz: Sz,
7618 o2: u1 = 0b1,
7619 decoded24: u5 = 0b11110,
7620 U: std.builtin.Signedness = .signed,
7621 decoded30: u2 = 0b01,
7622 };
7623
7624 /// C7.2.84 FCVTPS (vector)
7625 pub const Fcvtps = packed struct {
7626 Rd: Register.Encoded,
7627 Rn: Register.Encoded,
7628 decoded10: u2 = 0b10,
7629 opcode: u5 = 0b11010,
7630 decoded17: u5 = 0b10000,
7631 sz: Sz,
7632 o2: u1 = 0b1,
7633 decoded24: u5 = 0b11110,
7634 U: std.builtin.Signedness = .signed,
7635 decoded30: u2 = 0b01,
7636 };
7637
7638 /// C7.2.90 FCVTZS (vector, integer)
7639 pub const Fcvtzs = packed struct {
7640 Rd: Register.Encoded,
7641 Rn: Register.Encoded,
7642 decoded10: u2 = 0b10,
7643 opcode: u5 = 0b11011,
7644 decoded17: u5 = 0b10000,
7645 sz: Sz,
7646 o2: u1 = 0b1,
7647 decoded24: u5 = 0b11110,
7648 U: std.builtin.Signedness = .signed,
7649 decoded30: u2 = 0b01,
7650 };
7651
7652 /// C7.2.144 FRECPE
7653 pub const Frecpe = packed struct {
7654 Rd: Register.Encoded,
7655 Rn: Register.Encoded,
7656 decoded10: u2 = 0b10,
7657 opcode: u5 = 0b11101,
7658 decoded17: u5 = 0b10000,
7659 sz: Sz,
7660 o2: u1 = 0b1,
7661 decoded24: u5 = 0b11110,
7662 U: std.builtin.Signedness = .signed,
7663 decoded30: u2 = 0b01,
7664 };
7665
7666 /// C7.2.146 FRECPX
7667 pub const Frecpx = packed struct {
7668 Rd: Register.Encoded,
7669 Rn: Register.Encoded,
7670 decoded10: u2 = 0b10,
7671 opcode: u5 = 0b11111,
7672 decoded17: u5 = 0b10000,
7673 sz: Sz,
7674 o2: u1 = 0b1,
7675 decoded24: u5 = 0b11110,
7676 U: std.builtin.Signedness = .signed,
7677 decoded30: u2 = 0b01,
7678 };
7679
7680 /// C7.2.394 USQADD
7681 pub const Usqadd = packed struct {
7682 Rd: Register.Encoded,
7683 Rn: Register.Encoded,
7684 decoded10: u2 = 0b10,
7685 opcode: u5 = 0b00011,
7686 decoded17: u5 = 0b10000,
7687 size: Size,
7688 decoded24: u5 = 0b11110,
7689 U: std.builtin.Signedness = .unsigned,
7690 decoded30: u2 = 0b01,
7691 };
7692
7693 /// C7.2.292 SQNEG
7694 pub const Sqneg = packed struct {
7695 Rd: Register.Encoded,
7696 Rn: Register.Encoded,
7697 decoded10: u2 = 0b10,
7698 opcode: u5 = 0b00111,
7699 decoded17: u5 = 0b10000,
7700 size: Size,
7701 decoded24: u5 = 0b11110,
7702 U: std.builtin.Signedness = .unsigned,
7703 decoded30: u2 = 0b01,
7704 };
7705
7706 /// C7.2.30 CMGE (zero)
7707 pub const Cmge = packed struct {
7708 Rd: Register.Encoded,
7709 Rn: Register.Encoded,
7710 decoded10: u2 = 0b10,
7711 opcode: u5 = 0b01000,
7712 decoded17: u5 = 0b10000,
7713 size: Size,
7714 decoded24: u5 = 0b11110,
7715 U: std.builtin.Signedness = .unsigned,
7716 decoded30: u2 = 0b01,
7717 };
7718
7719 /// C7.2.35 CMLE (zero)
7720 pub const Cmle = packed struct {
7721 Rd: Register.Encoded,
7722 Rn: Register.Encoded,
7723 decoded10: u2 = 0b10,
7724 opcode: u5 = 0b01001,
7725 decoded17: u5 = 0b10000,
7726 size: Size,
7727 decoded24: u5 = 0b11110,
7728 U: std.builtin.Signedness = .unsigned,
7729 decoded30: u2 = 0b01,
7730 };
7731
7732 /// C7.2.209 NEG (vector)
7733 pub const Neg = packed struct {
7734 Rd: Register.Encoded,
7735 Rn: Register.Encoded,
7736 decoded10: u2 = 0b10,
7737 opcode: u5 = 0b01011,
7738 decoded17: u5 = 0b10000,
7739 size: Size,
7740 decoded24: u5 = 0b11110,
7741 U: std.builtin.Signedness = .unsigned,
7742 decoded30: u2 = 0b01,
7743 };
7744
7745 /// C7.2.309 SQXTUN
7746 pub const Sqxtun = packed struct {
7747 Rd: Register.Encoded,
7748 Rn: Register.Encoded,
7749 decoded10: u2 = 0b10,
7750 opcode: u5 = 0b10010,
7751 decoded17: u5 = 0b10000,
7752 size: Size,
7753 decoded24: u5 = 0b11110,
7754 U: std.builtin.Signedness = .unsigned,
7755 decoded30: u2 = 0b01,
7756 };
7757
7758 /// C7.2.381 UQXTN
7759 pub const Uqxtn = packed struct {
7760 Rd: Register.Encoded,
7761 Rn: Register.Encoded,
7762 decoded10: u2 = 0b10,
7763 opcode: u5 = 0b10100,
7764 decoded17: u5 = 0b10000,
7765 size: Size,
7766 decoded24: u5 = 0b11110,
7767 U: std.builtin.Signedness = .unsigned,
7768 decoded30: u2 = 0b01,
7769 };
7770
7771 /// C7.2.88 FCVTXN
7772 pub const Fcvtxn = packed struct {
7773 Rd: Register.Encoded,
7774 Rn: Register.Encoded,
7775 decoded10: u2 = 0b10,
7776 opcode: u5 = 0b10110,
7777 decoded17: u5 = 0b10000,
7778 sz: Sz,
7779 o2: u1 = 0b0,
7780 decoded24: u5 = 0b11110,
7781 U: std.builtin.Signedness = .unsigned,
7782 decoded30: u2 = 0b01,
7783 };
7784
7785 /// C7.2.82 FCVTNU (vector)
7786 pub const Fcvtnu = packed struct {
7787 Rd: Register.Encoded,
7788 Rn: Register.Encoded,
7789 decoded10: u2 = 0b10,
7790 opcode: u5 = 0b11010,
7791 decoded17: u5 = 0b10000,
7792 sz: Sz,
7793 o2: u1 = 0b0,
7794 decoded24: u5 = 0b11110,
7795 U: std.builtin.Signedness = .unsigned,
7796 decoded30: u2 = 0b01,
7797 };
7798
7799 /// C7.2.77 FCVTMU (vector)
7800 pub const Fcvtmu = packed struct {
7801 Rd: Register.Encoded,
7802 Rn: Register.Encoded,
7803 decoded10: u2 = 0b10,
7804 opcode: u5 = 0b11011,
7805 decoded17: u5 = 0b10000,
7806 sz: Sz,
7807 o2: u1 = 0b0,
7808 decoded24: u5 = 0b11110,
7809 U: std.builtin.Signedness = .unsigned,
7810 decoded30: u2 = 0b01,
7811 };
7812
7813 /// C7.2.72 FCVTAU (vector)
7814 pub const Fcvtau = packed struct {
7815 Rd: Register.Encoded,
7816 Rn: Register.Encoded,
7817 decoded10: u2 = 0b10,
7818 opcode: u5 = 0b11100,
7819 decoded17: u5 = 0b10000,
7820 sz: Sz,
7821 o2: u1 = 0b0,
7822 decoded24: u5 = 0b11110,
7823 U: std.builtin.Signedness = .unsigned,
7824 decoded30: u2 = 0b01,
7825 };
7826
7827 /// C7.2.353 UCVTF (vector, integer)
7828 pub const Ucvtf = packed struct {
7829 Rd: Register.Encoded,
7830 Rn: Register.Encoded,
7831 decoded10: u2 = 0b10,
7832 opcode: u5 = 0b11101,
7833 decoded17: u5 = 0b10000,
7834 sz: Sz,
7835 o2: u1 = 0b0,
7836 decoded24: u5 = 0b11110,
7837 U: std.builtin.Signedness = .unsigned,
7838 decoded30: u2 = 0b01,
7839 };
7840
7841 /// C7.2.59 FCMGE (zero)
7842 pub const Fcmge = packed struct {
7843 Rd: Register.Encoded,
7844 Rn: Register.Encoded,
7845 decoded10: u2 = 0b10,
7846 opcode: u5 = 0b01100,
7847 decoded17: u5 = 0b10000,
7848 sz: Sz,
7849 o2: u1 = 0b1,
7850 decoded24: u5 = 0b11110,
7851 U: std.builtin.Signedness = .unsigned,
7852 decoded30: u2 = 0b01,
7853 };
7854
7855 /// C7.2.64 FCMLE (zero)
7856 pub const Fcmle = packed struct {
7857 Rd: Register.Encoded,
7858 Rn: Register.Encoded,
7859 decoded10: u2 = 0b10,
7860 opcode: u5 = 0b01101,
7861 decoded17: u5 = 0b10000,
7862 sz: Sz,
7863 o2: u1 = 0b1,
7864 decoded24: u5 = 0b11110,
7865 U: std.builtin.Signedness = .unsigned,
7866 decoded30: u2 = 0b01,
7867 };
7868
7869 /// C7.2.86 FCVTPU (vector)
7870 pub const Fcvtpu = packed struct {
7871 Rd: Register.Encoded,
7872 Rn: Register.Encoded,
7873 decoded10: u2 = 0b10,
7874 opcode: u5 = 0b11010,
7875 decoded17: u5 = 0b10000,
7876 sz: Sz,
7877 o2: u1 = 0b1,
7878 decoded24: u5 = 0b11110,
7879 U: std.builtin.Signedness = .unsigned,
7880 decoded30: u2 = 0b01,
7881 };
7882
7883 /// C7.2.94 FCVTZU (vector, integer)
7884 pub const Fcvtzu = packed struct {
7885 Rd: Register.Encoded,
7886 Rn: Register.Encoded,
7887 decoded10: u2 = 0b10,
7888 opcode: u5 = 0b11011,
7889 decoded17: u5 = 0b10000,
7890 sz: Sz,
7891 o2: u1 = 0b1,
7892 decoded24: u5 = 0b11110,
7893 U: std.builtin.Signedness = .unsigned,
7894 decoded30: u2 = 0b01,
7895 };
7896
7897 /// C7.2.169 FRSQRTE
7898 pub const Frsqrte = packed struct {
7899 Rd: Register.Encoded,
7900 Rn: Register.Encoded,
7901 decoded10: u2 = 0b10,
7902 opcode: u5 = 0b11101,
7903 decoded17: u5 = 0b10000,
7904 sz: Sz,
7905 o2: u1 = 0b1,
7906 decoded24: u5 = 0b11110,
7907 U: std.builtin.Signedness = .unsigned,
7908 decoded30: u2 = 0b01,
7909 };
7910
7911 pub const Decoded = union(enum) {
7912 unallocated,
7913 suqadd: Suqadd,
7914 sqabs: Sqabs,
7915 cmgt: Cmgt,
7916 cmeq: Cmeq,
7917 cmlt: Cmlt,
7918 abs: Abs,
7919 sqxtn: Sqxtn,
7920 fcvtns: Fcvtns,
7921 fcvtms: Fcvtms,
7922 fcvtas: Fcvtas,
7923 scvtf: Scvtf,
7924 fcmgt: Fcmgt,
7925 fcmeq: Fcmeq,
7926 fcmlt: Fcmlt,
7927 fcvtps: Fcvtps,
7928 fcvtzs: Fcvtzs,
7929 frecpe: Frecpe,
7930 frecpx: Frecpx,
7931 usqadd: Usqadd,
7932 sqneg: Sqneg,
7933 cmge: Cmge,
7934 cmle: Cmle,
7935 neg: Neg,
7936 sqxtun: Sqxtun,
7937 uqxtn: Uqxtn,
7938 fcvtxn: Fcvtxn,
7939 fcvtnu: Fcvtnu,
7940 fcvtmu: Fcvtmu,
7941 fcvtau: Fcvtau,
7942 ucvtf: Ucvtf,
7943 fcmge: Fcmge,
7944 fcmle: Fcmle,
7945 fcvtpu: Fcvtpu,
7946 fcvtzu: Fcvtzu,
7947 frsqrte: Frsqrte,
7948 };
7949 pub fn decode(inst: @This()) @This().Decoded {
7950 return switch (inst.group.U) {
7951 .signed => switch (inst.group.opcode) {
7952 else => .unallocated,
7953 0b00011 => .{ .suqadd = inst.suqadd },
7954 0b00111 => .{ .sqabs = inst.sqabs },
7955 0b01000 => .{ .cmgt = inst.cmgt },
7956 0b01001 => .{ .cmeq = inst.cmeq },
7957 0b01010 => .{ .cmlt = inst.cmlt },
7958 0b01011 => .{ .abs = inst.abs },
7959 0b10100 => .{ .sqxtn = inst.sqxtn },
7960 0b11010 => switch (inst.group.size) {
7961 .byte, .half => .{ .fcvtns = inst.fcvtns },
7962 .single, .double => .{ .fcvtps = inst.fcvtps },
7963 },
7964 0b11011 => switch (inst.group.size) {
7965 .byte, .half => .{ .fcvtms = inst.fcvtms },
7966 .single, .double => .{ .fcvtzs = inst.fcvtzs },
7967 },
7968 0b11100 => switch (inst.group.size) {
7969 .byte, .half => .{ .fcvtas = inst.fcvtas },
7970 .single, .double => .unallocated,
7971 },
7972 0b11101 => switch (inst.group.size) {
7973 .byte, .half => .{ .scvtf = inst.scvtf },
7974 .single, .double => .{ .frecpe = inst.frecpe },
7975 },
7976 0b01100 => switch (inst.group.size) {
7977 .byte, .half => .unallocated,
7978 .single, .double => .{ .fcmgt = inst.fcmgt },
7979 },
7980 0b01101 => switch (inst.group.size) {
7981 .byte, .half => .unallocated,
7982 .single, .double => .{ .fcmeq = inst.fcmeq },
7983 },
7984 0b01110 => switch (inst.group.size) {
7985 .byte, .half => .unallocated,
7986 .single, .double => .{ .fcmlt = inst.fcmlt },
7987 },
7988 0b11111 => switch (inst.group.size) {
7989 .byte, .half => .unallocated,
7990 .single, .double => .{ .frecpx = inst.frecpx },
7991 },
7992 },
7993 .unsigned => switch (inst.group.opcode) {
7994 else => .unallocated,
7995 0b00011 => .{ .usqadd = inst.usqadd },
7996 0b00111 => .{ .sqneg = inst.sqneg },
7997 0b01000 => .{ .cmge = inst.cmge },
7998 0b01001 => .{ .cmle = inst.cmle },
7999 0b01011 => .{ .neg = inst.neg },
8000 0b10010 => .{ .sqxtun = inst.sqxtun },
8001 0b10100 => .{ .uqxtn = inst.uqxtn },
8002 0b10110 => switch (inst.group.size) {
8003 .byte, .half => .{ .fcvtxn = inst.fcvtxn },
8004 .single, .double => .unallocated,
8005 },
8006 0b11010 => switch (inst.group.size) {
8007 .byte, .half => .{ .fcvtnu = inst.fcvtnu },
8008 .single, .double => .{ .fcvtpu = inst.fcvtpu },
8009 },
8010 0b11011 => switch (inst.group.size) {
8011 .byte, .half => .{ .fcvtmu = inst.fcvtmu },
8012 .single, .double => .{ .fcvtzu = inst.fcvtzu },
8013 },
8014 0b11100 => switch (inst.group.size) {
8015 .byte, .half => .{ .fcvtau = inst.fcvtau },
8016 .single, .double => .unallocated,
8017 },
8018 0b11101 => switch (inst.group.size) {
8019 .byte, .half => .{ .ucvtf = inst.ucvtf },
8020 .single, .double => .{ .frsqrte = inst.frsqrte },
8021 },
8022 0b01100 => switch (inst.group.size) {
8023 .byte, .half => .unallocated,
8024 .single, .double => .{ .fcmge = inst.fcmge },
8025 },
8026 0b01101 => switch (inst.group.size) {
8027 .byte, .half => .unallocated,
8028 .single, .double => .{ .fcmle = inst.fcmle },
8029 },
8030 },
8031 };
8032 }
8033 };
8034
8035 /// Advanced SIMD scalar pairwise
8036 pub const SimdScalarPairwise = packed union {
8037 group: @This().Group,
8038 addp: Addp,
8039
8040 pub const Group = packed struct {
8041 Rd: Register.Encoded,
8042 Rn: Register.Encoded,
8043 decoded10: u2 = 0b10,
8044 opcode: u5,
8045 decoded17: u5 = 0b11000,
8046 size: Size,
8047 decoded24: u5 = 0b11110,
8048 U: std.builtin.Signedness,
8049 decoded30: u2 = 0b01,
8050 };
8051
8052 /// C7.2.4 ADDP (scalar)
8053 pub const Addp = packed struct {
8054 Rd: Register.Encoded,
8055 Rn: Register.Encoded,
8056 decoded10: u2 = 0b10,
8057 opcode: u5 = 0b11011,
8058 decoded17: u5 = 0b11000,
8059 size: Size,
8060 decoded24: u5 = 0b11110,
8061 U: std.builtin.Signedness = .signed,
8062 decoded30: u2 = 0b01,
8063 };
8064
8065 pub const Decoded = union(enum) {
8066 unallocated,
8067 addp: Addp,
8068 };
8069 pub fn decode(inst: @This()) @This().Decoded {
8070 return switch (inst.group.U) {
8071 .signed => switch (inst.group.opcode) {
8072 else => .unallocated,
8073 0b11011 => .{ .addp = inst.addp },
8074 },
8075 .unsigned => .unallocated,
8076 };
8077 }
8078 };
8079
8080 /// Advanced SIMD copy
8081 pub const SimdCopy = packed union {
8082 group: @This().Group,
8083 dup: Dup,
8084 smov: Smov,
8085 umov: Umov,
8086 ins: Ins,
8087
8088 pub const Group = packed struct {
8089 Rd: Register.Encoded,
8090 Rn: Register.Encoded,
8091 decoded10: u1 = 0b1,
8092 imm4: u4,
8093 decoded15: u1 = 0b0,
8094 imm5: u5,
8095 decoded21: u8 = 0b01110000,
8096 op: u1,
8097 Q: u1,
8098 decoded31: u1 = 0b0,
8099 };
8100
8101 /// C7.2.39 DUP (element)
8102 /// C7.2.40 DUP (general)
8103 pub const Dup = packed struct {
8104 Rd: Register.Encoded,
8105 Rn: Register.Encoded,
8106 decoded10: u1 = 0b1,
8107 imm4: Imm4,
8108 decoded15: u1 = 0b0,
8109 imm5: u5,
8110 decoded21: u8 = 0b01110000,
8111 op: u1 = 0b0,
8112 Q: Q,
8113 decoded31: u1 = 0b0,
8114
8115 pub const Imm4 = enum(u4) {
8116 element = 0b0000,
8117 general = 0b0001,
8118 _,
8119 };
8120 };
8121
8122 /// C7.2.279 SMOV
8123 pub const Smov = packed struct {
8124 Rd: Register.Encoded,
8125 Rn: Register.Encoded,
8126 decoded10: u1 = 0b1,
8127 imm4: u4 = 0b0101,
8128 decoded15: u1 = 0b0,
8129 imm5: u5,
8130 decoded21: u8 = 0b01110000,
8131 op: u1 = 0b0,
8132 Q: Register.GeneralSize,
8133 decoded31: u1 = 0b0,
8134 };
8135
8136 /// C7.2.371 UMOV
8137 pub const Umov = packed struct {
8138 Rd: Register.Encoded,
8139 Rn: Register.Encoded,
8140 decoded10: u1 = 0b1,
8141 imm4: u4 = 0b0111,
8142 decoded15: u1 = 0b0,
8143 imm5: u5,
8144 decoded21: u8 = 0b01110000,
8145 op: u1 = 0b0,
8146 Q: Register.GeneralSize,
8147 decoded31: u1 = 0b0,
8148 };
8149
8150 /// C7.2.175 INS (element)
8151 /// C7.2.176 INS (general)
8152 pub const Ins = packed struct {
8153 Rd: Register.Encoded,
8154 Rn: Register.Encoded,
8155 decoded10: u1 = 0b1,
8156 imm4: Imm4,
8157 decoded15: u1 = 0b0,
8158 imm5: u5,
8159 decoded21: u8 = 0b01110000,
8160 op: Op,
8161 Q: u1 = 0b1,
8162 decoded31: u1 = 0b0,
8163
8164 pub const Imm4 = packed union {
8165 element: u4,
8166 general: General,
8167
8168 pub const General = enum(u4) {
8169 general = 0b0011,
8170 _,
8171 };
8172 };
8173
8174 pub const Op = enum(u1) {
8175 general = 0b0,
8176 element = 0b1,
8177 };
8178 };
8179
8180 pub const Decoded = union(enum) {
8181 unallocated,
8182 dup: Dup,
8183 smov: Smov,
8184 umov: Umov,
8185 ins: Ins,
8186 };
8187 pub fn decode(inst: @This()) @This().Decoded {
8188 return switch (inst.group.op) {
8189 0b0 => switch (inst.group.imm4) {
8190 0b0000, 0b0001 => .{ .dup = inst.dup },
8191 else => .unallocated,
8192 0b0101 => switch (@ctz(inst.group.imm5)) {
8193 0, 1 => .{ .smov = inst.smov },
8194 2 => switch (inst.group.Q) {
8195 0b1 => .{ .smov = inst.smov },
8196 0b0 => .unallocated,
8197 },
8198 else => .unallocated,
8199 },
8200 0b0111 => switch (@ctz(inst.group.imm5)) {
8201 0, 1, 2 => switch (inst.group.Q) {
8202 0b0 => .{ .umov = inst.umov },
8203 0b1 => .unallocated,
8204 },
8205 3 => switch (inst.group.Q) {
8206 0b1 => .{ .umov = inst.umov },
8207 0b0 => .unallocated,
8208 },
8209 else => .unallocated,
8210 },
8211 0b0011 => switch (inst.group.Q) {
8212 0b0 => .unallocated,
8213 0b1 => .{ .ins = inst.ins },
8214 },
8215 },
8216 0b1 => switch (inst.group.Q) {
8217 0b0 => .unallocated,
8218 0b1 => .{ .ins = inst.ins },
8219 },
8220 };
8221 }
8222 };
8223
8224 /// Advanced SIMD two-register miscellaneous (FP16)
8225 pub const SimdTwoRegisterMiscellaneousFp16 = packed union {
8226 group: @This().Group,
8227 frintn: Frintn,
8228 frintm: Frintm,
8229 fcvtns: Fcvtns,
8230 fcvtms: Fcvtms,
8231 fcvtas: Fcvtas,
8232 scvtf: Scvtf,
8233 fcmgt: Fcmgt,
8234 fcmeq: Fcmeq,
8235 fcmlt: Fcmlt,
8236 fabs: Fabs,
8237 frintp: Frintp,
8238 frintz: Frintz,
8239 fcvtps: Fcvtps,
8240 fcvtzs: Fcvtzs,
8241 frecpe: Frecpe,
8242 frinta: Frinta,
8243 frintx: Frintx,
8244 fcvtnu: Fcvtnu,
8245 fcvtmu: Fcvtmu,
8246 fcvtau: Fcvtau,
8247 ucvtf: Ucvtf,
8248 fcmge: Fcmge,
8249 fcmle: Fcmle,
8250 fneg: Fneg,
8251 frinti: Frinti,
8252 fcvtpu: Fcvtpu,
8253 fcvtzu: Fcvtzu,
8254 frsqrte: Frsqrte,
8255 fsqrt: Fsqrt,
8256
8257 pub const Group = packed struct {
8258 Rd: Register.Encoded,
8259 Rn: Register.Encoded,
8260 decoded10: u2 = 0b10,
8261 opcode: u5,
8262 decoded17: u6 = 0b111100,
8263 a: u1,
8264 decoded24: u5 = 0b01110,
8265 U: std.builtin.Signedness,
8266 Q: Q,
8267 decoded31: u1 = 0b0,
8268 };
8269
8270 /// C7.2.161 FRINTN (vector)
8271 pub const Frintn = packed struct {
8272 Rd: Register.Encoded,
8273 Rn: Register.Encoded,
8274 decoded10: u2 = 0b10,
8275 opcode: u5 = 0b11000,
8276 decoded17: u6 = 0b111100,
8277 o2: u1 = 0b0,
8278 decoded24: u5 = 0b01110,
8279 U: std.builtin.Signedness = .signed,
8280 Q: Q,
8281 decoded31: u1 = 0b0,
8282 };
8283
8284 /// C7.2.159 FRINTM (vector)
8285 pub const Frintm = packed struct {
8286 Rd: Register.Encoded,
8287 Rn: Register.Encoded,
8288 decoded10: u2 = 0b10,
8289 opcode: u5 = 0b11001,
8290 decoded17: u6 = 0b111100,
8291 o2: u1 = 0b0,
8292 decoded24: u5 = 0b01110,
8293 U: std.builtin.Signedness = .signed,
8294 Q: Q,
8295 decoded31: u1 = 0b0,
8296 };
8297
8298 /// C7.2.80 FCVTNS (vector)
8299 pub const Fcvtns = packed struct {
8300 Rd: Register.Encoded,
8301 Rn: Register.Encoded,
8302 decoded10: u2 = 0b10,
8303 opcode: u5 = 0b11010,
8304 decoded17: u6 = 0b111100,
8305 o2: u1 = 0b0,
8306 decoded24: u5 = 0b01110,
8307 U: std.builtin.Signedness = .signed,
8308 Q: Q,
8309 decoded31: u1 = 0b0,
8310 };
8311
8312 /// C7.2.75 FCVTMS (vector)
8313 pub const Fcvtms = packed struct {
8314 Rd: Register.Encoded,
8315 Rn: Register.Encoded,
8316 decoded10: u2 = 0b10,
8317 opcode: u5 = 0b11011,
8318 decoded17: u6 = 0b111100,
8319 o2: u1 = 0b0,
8320 decoded24: u5 = 0b01110,
8321 U: std.builtin.Signedness = .signed,
8322 Q: Q,
8323 decoded31: u1 = 0b0,
8324 };
8325
8326 /// C7.2.70 FCVTAS (vector)
8327 pub const Fcvtas = packed struct {
8328 Rd: Register.Encoded,
8329 Rn: Register.Encoded,
8330 decoded10: u2 = 0b10,
8331 opcode: u5 = 0b11100,
8332 decoded17: u6 = 0b111100,
8333 o2: u1 = 0b0,
8334 decoded24: u5 = 0b01110,
8335 U: std.builtin.Signedness = .signed,
8336 Q: Q,
8337 decoded31: u1 = 0b0,
8338 };
8339
8340 /// C7.2.234 SCVTF (vector, integer)
8341 pub const Scvtf = packed struct {
8342 Rd: Register.Encoded,
8343 Rn: Register.Encoded,
8344 decoded10: u2 = 0b10,
8345 opcode: u5 = 0b11101,
8346 decoded17: u6 = 0b111100,
8347 o2: u1 = 0b0,
8348 decoded24: u5 = 0b01110,
8349 U: std.builtin.Signedness = .signed,
8350 Q: Q,
8351 decoded31: u1 = 0b0,
8352 };
8353
8354 /// C7.2.61 FCMGT (zero)
8355 pub const Fcmgt = packed struct {
8356 Rd: Register.Encoded,
8357 Rn: Register.Encoded,
8358 decoded10: u2 = 0b10,
8359 opcode: u5 = 0b01100,
8360 decoded17: u6 = 0b111100,
8361 o2: u1 = 0b1,
8362 decoded24: u5 = 0b01110,
8363 U: std.builtin.Signedness = .signed,
8364 Q: Q,
8365 decoded31: u1 = 0b0,
8366 };
8367
8368 /// C7.2.57 FCMEQ (zero)
8369 pub const Fcmeq = packed struct {
8370 Rd: Register.Encoded,
8371 Rn: Register.Encoded,
8372 decoded10: u2 = 0b10,
8373 opcode: u5 = 0b01101,
8374 decoded17: u6 = 0b111100,
8375 o2: u1 = 0b1,
8376 decoded24: u5 = 0b01110,
8377 U: std.builtin.Signedness = .signed,
8378 Q: Q,
8379 decoded31: u1 = 0b0,
8380 };
8381
8382 /// C7.2.65 FCMLT (zero)
8383 pub const Fcmlt = packed struct {
8384 Rd: Register.Encoded,
8385 Rn: Register.Encoded,
8386 decoded10: u2 = 0b10,
8387 opcode: u5 = 0b01110,
8388 decoded17: u6 = 0b111100,
8389 o2: u1 = 0b1,
8390 decoded24: u5 = 0b01110,
8391 U: std.builtin.Signedness = .signed,
8392 Q: Q,
8393 decoded31: u1 = 0b0,
8394 };
8395
8396 /// C7.2.45 FABS (vector)
8397 pub const Fabs = packed struct {
8398 Rd: Register.Encoded,
8399 Rn: Register.Encoded,
8400 decoded10: u2 = 0b10,
8401 opcode: u5 = 0b01111,
8402 decoded17: u6 = 0b111100,
8403 o2: u1 = 0b1,
8404 decoded24: u5 = 0b01110,
8405 U: std.builtin.Signedness = .signed,
8406 Q: Q,
8407 decoded31: u1 = 0b0,
8408 };
8409
8410 /// C7.2.163 FRINTP (vector)
8411 pub const Frintp = packed struct {
8412 Rd: Register.Encoded,
8413 Rn: Register.Encoded,
8414 decoded10: u2 = 0b10,
8415 opcode: u5 = 0b11000,
8416 decoded17: u6 = 0b111100,
8417 o2: u1 = 0b1,
8418 decoded24: u5 = 0b01110,
8419 U: std.builtin.Signedness = .signed,
8420 Q: Q,
8421 decoded31: u1 = 0b0,
8422 };
8423
8424 /// C7.2.167 FRINTZ (vector)
8425 pub const Frintz = packed struct {
8426 Rd: Register.Encoded,
8427 Rn: Register.Encoded,
8428 decoded10: u2 = 0b10,
8429 opcode: u5 = 0b11001,
8430 decoded17: u6 = 0b111100,
8431 o2: u1 = 0b1,
8432 decoded24: u5 = 0b01110,
8433 U: std.builtin.Signedness = .signed,
8434 Q: Q,
8435 decoded31: u1 = 0b0,
8436 };
8437
8438 /// C7.2.84 FCVTPS (vector)
8439 pub const Fcvtps = packed struct {
8440 Rd: Register.Encoded,
8441 Rn: Register.Encoded,
8442 decoded10: u2 = 0b10,
8443 opcode: u5 = 0b11010,
8444 decoded17: u6 = 0b111100,
8445 o2: u1 = 0b1,
8446 decoded24: u5 = 0b01110,
8447 U: std.builtin.Signedness = .signed,
8448 Q: Q,
8449 decoded31: u1 = 0b0,
8450 };
8451
8452 /// C7.2.90 FCVTZS (vector, integer)
8453 pub const Fcvtzs = packed struct {
8454 Rd: Register.Encoded,
8455 Rn: Register.Encoded,
8456 decoded10: u2 = 0b10,
8457 opcode: u5 = 0b11011,
8458 decoded17: u6 = 0b111100,
8459 o2: u1 = 0b1,
8460 decoded24: u5 = 0b01110,
8461 U: std.builtin.Signedness = .signed,
8462 Q: Q,
8463 decoded31: u1 = 0b0,
8464 };
8465
8466 /// C7.2.144 FRECPE
8467 pub const Frecpe = packed struct {
8468 Rd: Register.Encoded,
8469 Rn: Register.Encoded,
8470 decoded10: u2 = 0b10,
8471 opcode: u5 = 0b11101,
8472 decoded17: u6 = 0b111100,
8473 o2: u1 = 0b1,
8474 decoded24: u5 = 0b01110,
8475 U: std.builtin.Signedness = .signed,
8476 Q: Q,
8477 decoded31: u1 = 0b0,
8478 };
8479
8480 /// C7.2.155 FRINTA (vector)
8481 pub const Frinta = packed struct {
8482 Rd: Register.Encoded,
8483 Rn: Register.Encoded,
8484 decoded10: u2 = 0b10,
8485 opcode: u5 = 0b11000,
8486 decoded17: u6 = 0b111100,
8487 o2: u1 = 0b0,
8488 decoded24: u5 = 0b01110,
8489 U: std.builtin.Signedness = .unsigned,
8490 Q: Q,
8491 decoded31: u1 = 0b0,
8492 };
8493
8494 /// C7.2.159 FRINTX (vector)
8495 pub const Frintx = packed struct {
8496 Rd: Register.Encoded,
8497 Rn: Register.Encoded,
8498 decoded10: u2 = 0b10,
8499 opcode: u5 = 0b11001,
8500 decoded17: u6 = 0b111100,
8501 o2: u1 = 0b0,
8502 decoded24: u5 = 0b01110,
8503 U: std.builtin.Signedness = .unsigned,
8504 Q: Q,
8505 decoded31: u1 = 0b0,
8506 };
8507
8508 /// C7.2.82 FCVTNU (vector)
8509 pub const Fcvtnu = packed struct {
8510 Rd: Register.Encoded,
8511 Rn: Register.Encoded,
8512 decoded10: u2 = 0b10,
8513 opcode: u5 = 0b11010,
8514 decoded17: u6 = 0b111100,
8515 o2: u1 = 0b0,
8516 decoded24: u5 = 0b01110,
8517 U: std.builtin.Signedness = .unsigned,
8518 Q: Q,
8519 decoded31: u1 = 0b0,
8520 };
8521
8522 /// C7.2.77 FCVTMU (vector)
8523 pub const Fcvtmu = packed struct {
8524 Rd: Register.Encoded,
8525 Rn: Register.Encoded,
8526 decoded10: u2 = 0b10,
8527 opcode: u5 = 0b11011,
8528 decoded17: u6 = 0b111100,
8529 o2: u1 = 0b0,
8530 decoded24: u5 = 0b01110,
8531 U: std.builtin.Signedness = .unsigned,
8532 Q: Q,
8533 decoded31: u1 = 0b0,
8534 };
8535
8536 /// C7.2.72 FCVTAU (vector)
8537 pub const Fcvtau = packed struct {
8538 Rd: Register.Encoded,
8539 Rn: Register.Encoded,
8540 decoded10: u2 = 0b10,
8541 opcode: u5 = 0b11100,
8542 decoded17: u6 = 0b111100,
8543 o2: u1 = 0b0,
8544 decoded24: u5 = 0b01110,
8545 U: std.builtin.Signedness = .unsigned,
8546 Q: Q,
8547 decoded31: u1 = 0b0,
8548 };
8549
8550 /// C7.2.353 UCVTF (vector, integer)
8551 pub const Ucvtf = packed struct {
8552 Rd: Register.Encoded,
8553 Rn: Register.Encoded,
8554 decoded10: u2 = 0b10,
8555 opcode: u5 = 0b11101,
8556 decoded17: u6 = 0b111100,
8557 o2: u1 = 0b0,
8558 decoded24: u5 = 0b01110,
8559 U: std.builtin.Signedness = .unsigned,
8560 Q: Q,
8561 decoded31: u1 = 0b0,
8562 };
8563
8564 /// C7.2.59 FCMGE (zero)
8565 pub const Fcmge = packed struct {
8566 Rd: Register.Encoded,
8567 Rn: Register.Encoded,
8568 decoded10: u2 = 0b10,
8569 opcode: u5 = 0b01100,
8570 decoded17: u6 = 0b111100,
8571 o2: u1 = 0b1,
8572 decoded24: u5 = 0b01110,
8573 U: std.builtin.Signedness = .unsigned,
8574 Q: Q,
8575 decoded31: u1 = 0b0,
8576 };
8577
8578 /// C7.2.64 FCMLE (zero)
8579 pub const Fcmle = packed struct {
8580 Rd: Register.Encoded,
8581 Rn: Register.Encoded,
8582 decoded10: u2 = 0b10,
8583 opcode: u5 = 0b01101,
8584 decoded17: u6 = 0b111100,
8585 o2: u1 = 0b1,
8586 decoded24: u5 = 0b01110,
8587 U: std.builtin.Signedness = .unsigned,
8588 Q: Q,
8589 decoded31: u1 = 0b0,
8590 };
8591
8592 /// C7.2.139 FNEG (vector)
8593 pub const Fneg = packed struct {
8594 Rd: Register.Encoded,
8595 Rn: Register.Encoded,
8596 decoded10: u2 = 0b10,
8597 opcode: u5 = 0b01111,
8598 decoded17: u6 = 0b111100,
8599 o2: u1 = 0b1,
8600 decoded24: u5 = 0b01110,
8601 U: std.builtin.Signedness = .unsigned,
8602 Q: Q,
8603 decoded31: u1 = 0b0,
8604 };
8605
8606 /// C7.2.157 FRINTI (vector)
8607 pub const Frinti = packed struct {
8608 Rd: Register.Encoded,
8609 Rn: Register.Encoded,
8610 decoded10: u2 = 0b10,
8611 opcode: u5 = 0b11001,
8612 decoded17: u6 = 0b111100,
8613 o2: u1 = 0b1,
8614 decoded24: u5 = 0b01110,
8615 U: std.builtin.Signedness = .unsigned,
8616 Q: Q,
8617 decoded31: u1 = 0b0,
8618 };
8619
8620 /// C7.2.86 FCVTPU (vector)
8621 pub const Fcvtpu = packed struct {
8622 Rd: Register.Encoded,
8623 Rn: Register.Encoded,
8624 decoded10: u2 = 0b10,
8625 opcode: u5 = 0b11010,
8626 decoded17: u6 = 0b111100,
8627 o2: u1 = 0b1,
8628 decoded24: u5 = 0b01110,
8629 U: std.builtin.Signedness = .unsigned,
8630 Q: Q,
8631 decoded31: u1 = 0b0,
8632 };
8633
8634 /// C7.2.94 FCVTZU (vector, integer)
8635 pub const Fcvtzu = packed struct {
8636 Rd: Register.Encoded,
8637 Rn: Register.Encoded,
8638 decoded10: u2 = 0b10,
8639 opcode: u5 = 0b11011,
8640 decoded17: u6 = 0b111100,
8641 o2: u1 = 0b1,
8642 decoded24: u5 = 0b01110,
8643 U: std.builtin.Signedness = .unsigned,
8644 Q: Q,
8645 decoded31: u1 = 0b0,
8646 };
8647
8648 /// C7.2.169 FRSQRTE
8649 pub const Frsqrte = packed struct {
8650 Rd: Register.Encoded,
8651 Rn: Register.Encoded,
8652 decoded10: u2 = 0b10,
8653 opcode: u5 = 0b11101,
8654 decoded17: u6 = 0b111100,
8655 o2: u1 = 0b1,
8656 decoded24: u5 = 0b01110,
8657 U: std.builtin.Signedness = .unsigned,
8658 Q: Q,
8659 decoded31: u1 = 0b0,
8660 };
8661
8662 /// C7.2.171 FSQRT
8663 pub const Fsqrt = packed struct {
8664 Rd: Register.Encoded,
8665 Rn: Register.Encoded,
8666 decoded10: u2 = 0b10,
8667 opcode: u5 = 0b11111,
8668 decoded17: u6 = 0b111100,
8669 o2: u1 = 0b1,
8670 decoded24: u5 = 0b01110,
8671 U: std.builtin.Signedness = .unsigned,
8672 Q: Q,
8673 decoded31: u1 = 0b0,
8674 };
8675
8676 pub const Decoded = union(enum) {
8677 unallocated,
8678 frintn: Frintn,
8679 frintm: Frintm,
8680 fcvtns: Fcvtns,
8681 fcvtms: Fcvtms,
8682 fcvtas: Fcvtas,
8683 scvtf: Scvtf,
8684 fcmgt: Fcmgt,
8685 fcmeq: Fcmeq,
8686 fcmlt: Fcmlt,
8687 fabs: Fabs,
8688 frintp: Frintp,
8689 frintz: Frintz,
8690 fcvtps: Fcvtps,
8691 fcvtzs: Fcvtzs,
8692 frecpe: Frecpe,
8693 frinta: Frinta,
8694 frintx: Frintx,
8695 fcvtnu: Fcvtnu,
8696 fcvtmu: Fcvtmu,
8697 fcvtau: Fcvtau,
8698 ucvtf: Ucvtf,
8699 fcmge: Fcmge,
8700 fcmle: Fcmle,
8701 fneg: Fneg,
8702 frinti: Frinti,
8703 fcvtpu: Fcvtpu,
8704 fcvtzu: Fcvtzu,
8705 frsqrte: Frsqrte,
8706 fsqrt: Fsqrt,
8707 };
8708 pub fn decode(inst: @This()) @This().Decoded {
8709 return switch (inst.group.U) {
8710 .signed => switch (inst.group.a) {
8711 0b0 => switch (inst.group.opcode) {
8712 else => .unallocated,
8713 0b11000 => .{ .frintn = inst.frintn },
8714 0b11001 => .{ .frintm = inst.frintm },
8715 0b11010 => .{ .fcvtns = inst.fcvtns },
8716 0b11011 => .{ .fcvtms = inst.fcvtms },
8717 0b11100 => .{ .fcvtas = inst.fcvtas },
8718 0b11101 => .{ .scvtf = inst.scvtf },
8719 },
8720 0b1 => switch (inst.group.opcode) {
8721 else => .unallocated,
8722 0b01100 => .{ .fcmgt = inst.fcmgt },
8723 0b01101 => .{ .fcmeq = inst.fcmeq },
8724 0b01110 => .{ .fcmlt = inst.fcmlt },
8725 0b01111 => .{ .fabs = inst.fabs },
8726 0b11000 => .{ .frintp = inst.frintp },
8727 0b11001 => .{ .frintz = inst.frintz },
8728 0b11010 => .{ .fcvtps = inst.fcvtps },
8729 0b11011 => .{ .fcvtzs = inst.fcvtzs },
8730 0b11101 => .{ .frecpe = inst.frecpe },
8731 },
8732 },
8733 .unsigned => switch (inst.group.a) {
8734 0b0 => switch (inst.group.opcode) {
8735 else => .unallocated,
8736 0b11000 => .{ .frinta = inst.frinta },
8737 0b11001 => .{ .frintx = inst.frintx },
8738 0b11010 => .{ .fcvtnu = inst.fcvtnu },
8739 0b11011 => .{ .fcvtmu = inst.fcvtmu },
8740 0b11100 => .{ .fcvtau = inst.fcvtau },
8741 0b11101 => .{ .ucvtf = inst.ucvtf },
8742 },
8743 0b1 => switch (inst.group.opcode) {
8744 else => .unallocated,
8745 0b01100 => .{ .fcmge = inst.fcmge },
8746 0b01101 => .{ .fcmle = inst.fcmle },
8747 0b01111 => .{ .fneg = inst.fneg },
8748 0b11001 => .{ .frinti = inst.frinti },
8749 0b11010 => .{ .fcvtpu = inst.fcvtpu },
8750 0b11011 => .{ .fcvtzu = inst.fcvtzu },
8751 0b11101 => .{ .frsqrte = inst.frsqrte },
8752 0b11111 => .{ .fsqrt = inst.fsqrt },
8753 },
8754 },
8755 };
8756 }
8757 };
8758
8759 /// Advanced SIMD two-register miscellaneous
8760 pub const SimdTwoRegisterMiscellaneous = packed union {
8761 group: @This().Group,
8762 suqadd: Suqadd,
8763 cnt: Cnt,
8764 sqabs: Sqabs,
8765 cmgt: Cmgt,
8766 cmeq: Cmeq,
8767 cmlt: Cmlt,
8768 abs: Abs,
8769 sqxtn: Sqxtn,
8770 frintn: Frintn,
8771 frintm: Frintm,
8772 fcvtns: Fcvtns,
8773 fcvtms: Fcvtms,
8774 fcvtas: Fcvtas,
8775 scvtf: Scvtf,
8776 fcmgt: Fcmgt,
8777 fcmeq: Fcmeq,
8778 fcmlt: Fcmlt,
8779 fabs: Fabs,
8780 frintp: Frintp,
8781 frintz: Frintz,
8782 fcvtps: Fcvtps,
8783 fcvtzs: Fcvtzs,
8784 frecpe: Frecpe,
8785 usqadd: Usqadd,
8786 sqneg: Sqneg,
8787 cmge: Cmge,
8788 cmle: Cmle,
8789 neg: Neg,
8790 sqxtun: Sqxtun,
8791 uqxtn: Uqxtn,
8792 fcvtxn: Fcvtxn,
8793 frinta: Frinta,
8794 frintx: Frintx,
8795 fcvtnu: Fcvtnu,
8796 fcvtmu: Fcvtmu,
8797 fcvtau: Fcvtau,
8798 ucvtf: Ucvtf,
8799 not: Not,
8800 fcmge: Fcmge,
8801 fcmle: Fcmle,
8802 fneg: Fneg,
8803 frinti: Frinti,
8804 fcvtpu: Fcvtpu,
8805 fcvtzu: Fcvtzu,
8806 frsqrte: Frsqrte,
8807 fsqrt: Fsqrt,
8808
8809 pub const Group = packed struct {
8810 Rd: Register.Encoded,
8811 Rn: Register.Encoded,
8812 decoded10: u2 = 0b10,
8813 opcode: u5,
8814 decoded17: u5 = 0b10000,
8815 size: Size,
8816 decoded24: u5 = 0b01110,
8817 U: std.builtin.Signedness,
8818 Q: Q,
8819 decoded31: u1 = 0b0,
8820 };
8821
8822 /// C7.2.337 SUQADD
8823 pub const Suqadd = packed struct {
8824 Rd: Register.Encoded,
8825 Rn: Register.Encoded,
8826 decoded10: u2 = 0b10,
8827 opcode: u5 = 0b00011,
8828 decoded17: u5 = 0b10000,
8829 size: Size,
8830 decoded24: u5 = 0b01110,
8831 U: std.builtin.Signedness = .signed,
8832 Q: Q,
8833 decoded31: u1 = 0b0,
8834 };
8835
8836 /// C7.2.38 CNT
8837 pub const Cnt = packed struct {
8838 Rd: Register.Encoded,
8839 Rn: Register.Encoded,
8840 decoded10: u2 = 0b10,
8841 opcode: u5 = 0b00101,
8842 decoded17: u5 = 0b10000,
8843 size: Size,
8844 decoded24: u5 = 0b01110,
8845 U: std.builtin.Signedness = .signed,
8846 Q: Q,
8847 decoded31: u1 = 0b0,
8848 };
8849
8850 /// C7.2.282 SQABS
8851 pub const Sqabs = packed struct {
8852 Rd: Register.Encoded,
8853 Rn: Register.Encoded,
8854 decoded10: u2 = 0b10,
8855 opcode: u5 = 0b00111,
8856 decoded17: u5 = 0b10000,
8857 size: Size,
8858 decoded24: u5 = 0b01110,
8859 U: std.builtin.Signedness = .signed,
8860 Q: Q,
8861 decoded31: u1 = 0b0,
8862 };
8863
8864 /// C7.2.32 CMGT (zero)
8865 pub const Cmgt = packed struct {
8866 Rd: Register.Encoded,
8867 Rn: Register.Encoded,
8868 decoded10: u2 = 0b10,
8869 opcode: u5 = 0b01000,
8870 decoded17: u5 = 0b10000,
8871 size: Size,
8872 decoded24: u5 = 0b01110,
8873 U: std.builtin.Signedness = .signed,
8874 Q: Q,
8875 decoded31: u1 = 0b0,
8876 };
8877
8878 /// C7.2.28 CMEQ (zero)
8879 pub const Cmeq = packed struct {
8880 Rd: Register.Encoded,
8881 Rn: Register.Encoded,
8882 decoded10: u2 = 0b10,
8883 opcode: u5 = 0b01001,
8884 decoded17: u5 = 0b10000,
8885 size: Size,
8886 decoded24: u5 = 0b01110,
8887 U: std.builtin.Signedness = .signed,
8888 Q: Q,
8889 decoded31: u1 = 0b0,
8890 };
8891
8892 /// C7.2.36 CMLT (zero)
8893 pub const Cmlt = packed struct {
8894 Rd: Register.Encoded,
8895 Rn: Register.Encoded,
8896 decoded10: u2 = 0b10,
8897 opcode: u5 = 0b01010,
8898 decoded17: u5 = 0b10000,
8899 size: Size,
8900 decoded24: u5 = 0b01110,
8901 U: std.builtin.Signedness = .signed,
8902 Q: Q,
8903 decoded31: u1 = 0b0,
8904 };
8905
8906 /// C7.2.1 ABS
8907 pub const Abs = packed struct {
8908 Rd: Register.Encoded,
8909 Rn: Register.Encoded,
8910 decoded10: u2 = 0b10,
8911 opcode: u5 = 0b01011,
8912 decoded17: u5 = 0b10000,
8913 size: Size,
8914 decoded24: u5 = 0b01110,
8915 U: std.builtin.Signedness = .signed,
8916 Q: Q,
8917 decoded31: u1 = 0b0,
8918 };
8919
8920 /// C7.2.308 SQXTN, SQXTN2
8921 pub const Sqxtn = packed struct {
8922 Rd: Register.Encoded,
8923 Rn: Register.Encoded,
8924 decoded10: u2 = 0b10,
8925 opcode: u5 = 0b10100,
8926 decoded17: u5 = 0b10000,
8927 size: Size,
8928 decoded24: u5 = 0b01110,
8929 U: std.builtin.Signedness = .signed,
8930 Q: Q,
8931 decoded31: u1 = 0b0,
8932 };
8933
8934 /// C7.2.161 FRINTN (vector)
8935 pub const Frintn = packed struct {
8936 Rd: Register.Encoded,
8937 Rn: Register.Encoded,
8938 decoded10: u2 = 0b10,
8939 opcode: u5 = 0b11000,
8940 decoded17: u5 = 0b10000,
8941 sz: Sz,
8942 o2: u1 = 0b0,
8943 decoded24: u5 = 0b01110,
8944 U: std.builtin.Signedness = .signed,
8945 Q: Q,
8946 decoded31: u1 = 0b0,
8947 };
8948
8949 /// C7.2.159 FRINTM (vector)
8950 pub const Frintm = packed struct {
8951 Rd: Register.Encoded,
8952 Rn: Register.Encoded,
8953 decoded10: u2 = 0b10,
8954 opcode: u5 = 0b11001,
8955 decoded17: u5 = 0b10000,
8956 sz: Sz,
8957 o2: u1 = 0b0,
8958 decoded24: u5 = 0b01110,
8959 U: std.builtin.Signedness = .signed,
8960 Q: Q,
8961 decoded31: u1 = 0b0,
8962 };
8963
8964 /// C7.2.80 FCVTNS (vector)
8965 pub const Fcvtns = packed struct {
8966 Rd: Register.Encoded,
8967 Rn: Register.Encoded,
8968 decoded10: u2 = 0b10,
8969 opcode: u5 = 0b11010,
8970 decoded17: u5 = 0b10000,
8971 sz: Sz,
8972 o2: u1 = 0b0,
8973 decoded24: u5 = 0b01110,
8974 U: std.builtin.Signedness = .signed,
8975 Q: Q,
8976 decoded31: u1 = 0b0,
8977 };
8978
8979 /// C7.2.75 FCVTMS (vector)
8980 pub const Fcvtms = packed struct {
8981 Rd: Register.Encoded,
8982 Rn: Register.Encoded,
8983 decoded10: u2 = 0b10,
8984 opcode: u5 = 0b11011,
8985 decoded17: u5 = 0b10000,
8986 sz: Sz,
8987 o2: u1 = 0b0,
8988 decoded24: u5 = 0b01110,
8989 U: std.builtin.Signedness = .signed,
8990 Q: Q,
8991 decoded31: u1 = 0b0,
8992 };
8993
8994 /// C7.2.70 FCVTAS (vector)
8995 pub const Fcvtas = packed struct {
8996 Rd: Register.Encoded,
8997 Rn: Register.Encoded,
8998 decoded10: u2 = 0b10,
8999 opcode: u5 = 0b11100,
9000 decoded17: u5 = 0b10000,
9001 sz: Sz,
9002 o2: u1 = 0b0,
9003 decoded24: u5 = 0b01110,
9004 U: std.builtin.Signedness = .signed,
9005 Q: Q,
9006 decoded31: u1 = 0b0,
9007 };
9008
9009 /// C7.2.234 SCVTF (vector, integer)
9010 pub const Scvtf = packed struct {
9011 Rd: Register.Encoded,
9012 Rn: Register.Encoded,
9013 decoded10: u2 = 0b10,
9014 opcode: u5 = 0b11101,
9015 decoded17: u5 = 0b10000,
9016 sz: Sz,
9017 o2: u1 = 0b0,
9018 decoded24: u5 = 0b01110,
9019 U: std.builtin.Signedness = .signed,
9020 Q: Q,
9021 decoded31: u1 = 0b0,
9022 };
9023
9024 /// C7.2.61 FCMGT (zero)
9025 pub const Fcmgt = packed struct {
9026 Rd: Register.Encoded,
9027 Rn: Register.Encoded,
9028 decoded10: u2 = 0b10,
9029 opcode: u5 = 0b01100,
9030 decoded17: u5 = 0b10000,
9031 sz: Sz,
9032 o2: u1 = 0b1,
9033 decoded24: u5 = 0b01110,
9034 U: std.builtin.Signedness = .signed,
9035 Q: Q,
9036 decoded31: u1 = 0b0,
9037 };
9038
9039 /// C7.2.57 FCMEQ (zero)
9040 pub const Fcmeq = packed struct {
9041 Rd: Register.Encoded,
9042 Rn: Register.Encoded,
9043 decoded10: u2 = 0b10,
9044 opcode: u5 = 0b01101,
9045 decoded17: u5 = 0b10000,
9046 sz: Sz,
9047 o2: u1 = 0b1,
9048 decoded24: u5 = 0b01110,
9049 U: std.builtin.Signedness = .signed,
9050 Q: Q,
9051 decoded31: u1 = 0b0,
9052 };
9053
9054 /// C7.2.65 FCMLT (zero)
9055 pub const Fcmlt = packed struct {
9056 Rd: Register.Encoded,
9057 Rn: Register.Encoded,
9058 decoded10: u2 = 0b10,
9059 opcode: u5 = 0b01110,
9060 decoded17: u5 = 0b10000,
9061 sz: Sz,
9062 o2: u1 = 0b1,
9063 decoded24: u5 = 0b01110,
9064 U: std.builtin.Signedness = .signed,
9065 Q: Q,
9066 decoded31: u1 = 0b0,
9067 };
9068
9069 /// C7.2.45 FABS (vector)
9070 pub const Fabs = packed struct {
9071 Rd: Register.Encoded,
9072 Rn: Register.Encoded,
9073 decoded10: u2 = 0b10,
9074 opcode: u5 = 0b01111,
9075 decoded17: u5 = 0b10000,
9076 sz: Sz,
9077 o2: u1 = 0b1,
9078 decoded24: u5 = 0b01110,
9079 U: std.builtin.Signedness = .signed,
9080 Q: Q,
9081 decoded31: u1 = 0b0,
9082 };
9083
9084 /// C7.2.163 FRINTP (vector)
9085 pub const Frintp = packed struct {
9086 Rd: Register.Encoded,
9087 Rn: Register.Encoded,
9088 decoded10: u2 = 0b10,
9089 opcode: u5 = 0b11000,
9090 decoded17: u5 = 0b10000,
9091 sz: Sz,
9092 o2: u1 = 0b1,
9093 decoded24: u5 = 0b01110,
9094 U: std.builtin.Signedness = .signed,
9095 Q: Q,
9096 decoded31: u1 = 0b0,
9097 };
9098
9099 /// C7.2.167 FRINTZ (vector)
9100 pub const Frintz = packed struct {
9101 Rd: Register.Encoded,
9102 Rn: Register.Encoded,
9103 decoded10: u2 = 0b10,
9104 opcode: u5 = 0b11001,
9105 decoded17: u5 = 0b10000,
9106 sz: Sz,
9107 o2: u1 = 0b1,
9108 decoded24: u5 = 0b01110,
9109 U: std.builtin.Signedness = .signed,
9110 Q: Q,
9111 decoded31: u1 = 0b0,
9112 };
9113
9114 /// C7.2.84 FCVTPS (vector)
9115 pub const Fcvtps = packed struct {
9116 Rd: Register.Encoded,
9117 Rn: Register.Encoded,
9118 decoded10: u2 = 0b10,
9119 opcode: u5 = 0b11010,
9120 decoded17: u5 = 0b10000,
9121 sz: Sz,
9122 o2: u1 = 0b1,
9123 decoded24: u5 = 0b01110,
9124 U: std.builtin.Signedness = .signed,
9125 Q: Q,
9126 decoded31: u1 = 0b0,
9127 };
9128
9129 /// C7.2.90 FCVTZS (vector, integer)
9130 pub const Fcvtzs = packed struct {
9131 Rd: Register.Encoded,
9132 Rn: Register.Encoded,
9133 decoded10: u2 = 0b10,
9134 opcode: u5 = 0b11011,
9135 decoded17: u5 = 0b10000,
9136 sz: Sz,
9137 o2: u1 = 0b1,
9138 decoded24: u5 = 0b01110,
9139 U: std.builtin.Signedness = .signed,
9140 Q: Q,
9141 decoded31: u1 = 0b0,
9142 };
9143
9144 /// C7.2.144 FRECPE
9145 pub const Frecpe = packed struct {
9146 Rd: Register.Encoded,
9147 Rn: Register.Encoded,
9148 decoded10: u2 = 0b10,
9149 opcode: u5 = 0b11101,
9150 decoded17: u5 = 0b10000,
9151 sz: Sz,
9152 o2: u1 = 0b1,
9153 decoded24: u5 = 0b01110,
9154 U: std.builtin.Signedness = .signed,
9155 Q: Q,
9156 decoded31: u1 = 0b0,
9157 };
9158
9159 /// C7.2.394 USQADD
9160 pub const Usqadd = packed struct {
9161 Rd: Register.Encoded,
9162 Rn: Register.Encoded,
9163 decoded10: u2 = 0b10,
9164 opcode: u5 = 0b00011,
9165 decoded17: u5 = 0b10000,
9166 size: Size,
9167 decoded24: u5 = 0b01110,
9168 U: std.builtin.Signedness = .unsigned,
9169 Q: Q,
9170 decoded31: u1 = 0b0,
9171 };
9172
9173 /// C7.2.292 SQNEG
9174 pub const Sqneg = packed struct {
9175 Rd: Register.Encoded,
9176 Rn: Register.Encoded,
9177 decoded10: u2 = 0b10,
9178 opcode: u5 = 0b00111,
9179 decoded17: u5 = 0b10000,
9180 size: Size,
9181 decoded24: u5 = 0b01110,
9182 U: std.builtin.Signedness = .unsigned,
9183 Q: Q,
9184 decoded31: u1 = 0b0,
9185 };
9186
9187 /// C7.2.30 CMGE (zero)
9188 pub const Cmge = packed struct {
9189 Rd: Register.Encoded,
9190 Rn: Register.Encoded,
9191 decoded10: u2 = 0b10,
9192 opcode: u5 = 0b01000,
9193 decoded17: u5 = 0b10000,
9194 size: Size,
9195 decoded24: u5 = 0b01110,
9196 U: std.builtin.Signedness = .unsigned,
9197 Q: Q,
9198 decoded31: u1 = 0b0,
9199 };
9200
9201 /// C7.2.35 CMLE (zero)
9202 pub const Cmle = packed struct {
9203 Rd: Register.Encoded,
9204 Rn: Register.Encoded,
9205 decoded10: u2 = 0b10,
9206 opcode: u5 = 0b01001,
9207 decoded17: u5 = 0b10000,
9208 size: Size,
9209 decoded24: u5 = 0b01110,
9210 U: std.builtin.Signedness = .unsigned,
9211 Q: Q,
9212 decoded31: u1 = 0b0,
9213 };
9214
9215 /// C7.2.209 NEG (vector)
9216 pub const Neg = packed struct {
9217 Rd: Register.Encoded,
9218 Rn: Register.Encoded,
9219 decoded10: u2 = 0b10,
9220 opcode: u5 = 0b01011,
9221 decoded17: u5 = 0b10000,
9222 size: Size,
9223 decoded24: u5 = 0b01110,
9224 U: std.builtin.Signedness = .unsigned,
9225 Q: Q,
9226 decoded31: u1 = 0b0,
9227 };
9228
9229 /// C7.2.309 SQXTUN
9230 pub const Sqxtun = packed struct {
9231 Rd: Register.Encoded,
9232 Rn: Register.Encoded,
9233 decoded10: u2 = 0b10,
9234 opcode: u5 = 0b10010,
9235 decoded17: u5 = 0b10000,
9236 size: Size,
9237 decoded24: u5 = 0b01110,
9238 U: std.builtin.Signedness = .unsigned,
9239 Q: Q,
9240 decoded31: u1 = 0b0,
9241 };
9242
9243 /// C7.2.381 UQXTN
9244 pub const Uqxtn = packed struct {
9245 Rd: Register.Encoded,
9246 Rn: Register.Encoded,
9247 decoded10: u2 = 0b10,
9248 opcode: u5 = 0b10100,
9249 decoded17: u5 = 0b10000,
9250 size: Size,
9251 decoded24: u5 = 0b01110,
9252 U: std.builtin.Signedness = .unsigned,
9253 Q: Q,
9254 decoded31: u1 = 0b0,
9255 };
9256
9257 /// C7.2.88 FCVTXN
9258 pub const Fcvtxn = packed struct {
9259 Rd: Register.Encoded,
9260 Rn: Register.Encoded,
9261 decoded10: u2 = 0b10,
9262 opcode: u5 = 0b10110,
9263 decoded17: u5 = 0b10000,
9264 sz: Sz,
9265 o2: u1 = 0b0,
9266 decoded24: u5 = 0b01110,
9267 U: std.builtin.Signedness = .unsigned,
9268 Q: Q,
9269 decoded31: u1 = 0b0,
9270 };
9271
9272 /// C7.2.155 FRINTA (vector)
9273 pub const Frinta = packed struct {
9274 Rd: Register.Encoded,
9275 Rn: Register.Encoded,
9276 decoded10: u2 = 0b10,
9277 opcode: u5 = 0b11000,
9278 decoded17: u5 = 0b10000,
9279 sz: Sz,
9280 o2: u1 = 0b0,
9281 decoded24: u5 = 0b01110,
9282 U: std.builtin.Signedness = .unsigned,
9283 Q: Q,
9284 decoded31: u1 = 0b0,
9285 };
9286
9287 /// C7.2.165 FRINTX (vector)
9288 pub const Frintx = packed struct {
9289 Rd: Register.Encoded,
9290 Rn: Register.Encoded,
9291 decoded10: u2 = 0b10,
9292 opcode: u5 = 0b11001,
9293 decoded17: u5 = 0b10000,
9294 sz: Sz,
9295 o2: u1 = 0b0,
9296 decoded24: u5 = 0b01110,
9297 U: std.builtin.Signedness = .unsigned,
9298 Q: Q,
9299 decoded31: u1 = 0b0,
9300 };
9301
9302 /// C7.2.82 FCVTNU (vector)
9303 pub const Fcvtnu = packed struct {
9304 Rd: Register.Encoded,
9305 Rn: Register.Encoded,
9306 decoded10: u2 = 0b10,
9307 opcode: u5 = 0b11010,
9308 decoded17: u5 = 0b10000,
9309 sz: Sz,
9310 o2: u1 = 0b0,
9311 decoded24: u5 = 0b01110,
9312 U: std.builtin.Signedness = .unsigned,
9313 Q: Q,
9314 decoded31: u1 = 0b0,
9315 };
9316
9317 /// C7.2.77 FCVTMU (vector)
9318 pub const Fcvtmu = packed struct {
9319 Rd: Register.Encoded,
9320 Rn: Register.Encoded,
9321 decoded10: u2 = 0b10,
9322 opcode: u5 = 0b11011,
9323 decoded17: u5 = 0b10000,
9324 sz: Sz,
9325 o2: u1 = 0b0,
9326 decoded24: u5 = 0b01110,
9327 U: std.builtin.Signedness = .unsigned,
9328 Q: Q,
9329 decoded31: u1 = 0b0,
9330 };
9331
9332 /// C7.2.72 FCVTAU (vector)
9333 pub const Fcvtau = packed struct {
9334 Rd: Register.Encoded,
9335 Rn: Register.Encoded,
9336 decoded10: u2 = 0b10,
9337 opcode: u5 = 0b11100,
9338 decoded17: u5 = 0b10000,
9339 sz: Sz,
9340 o2: u1 = 0b0,
9341 decoded24: u5 = 0b01110,
9342 U: std.builtin.Signedness = .unsigned,
9343 Q: Q,
9344 decoded31: u1 = 0b0,
9345 };
9346
9347 /// C7.2.353 UCVTF (vector, integer)
9348 pub const Ucvtf = packed struct {
9349 Rd: Register.Encoded,
9350 Rn: Register.Encoded,
9351 decoded10: u2 = 0b10,
9352 opcode: u5 = 0b11101,
9353 decoded17: u5 = 0b10000,
9354 sz: Sz,
9355 o2: u1 = 0b0,
9356 decoded24: u5 = 0b01110,
9357 U: std.builtin.Signedness = .unsigned,
9358 Q: Q,
9359 decoded31: u1 = 0b0,
9360 };
9361
9362 /// C7.2.210 NOT
9363 pub const Not = packed struct {
9364 Rd: Register.Encoded,
9365 Rn: Register.Encoded,
9366 decoded10: u2 = 0b10,
9367 opcode: u5 = 0b00101,
9368 decoded17: u5 = 0b10000,
9369 size: Size = .byte,
9370 decoded24: u5 = 0b01110,
9371 U: std.builtin.Signedness = .unsigned,
9372 Q: Q,
9373 decoded31: u1 = 0b0,
9374 };
9375
9376 /// C7.2.59 FCMGE (zero)
9377 pub const Fcmge = packed struct {
9378 Rd: Register.Encoded,
9379 Rn: Register.Encoded,
9380 decoded10: u2 = 0b10,
9381 opcode: u5 = 0b01100,
9382 decoded17: u5 = 0b10000,
9383 sz: Sz,
9384 o2: u1 = 0b1,
9385 decoded24: u5 = 0b01110,
9386 U: std.builtin.Signedness = .unsigned,
9387 Q: Q,
9388 decoded31: u1 = 0b0,
9389 };
9390
9391 /// C7.2.64 FCMLE (zero)
9392 pub const Fcmle = packed struct {
9393 Rd: Register.Encoded,
9394 Rn: Register.Encoded,
9395 decoded10: u2 = 0b10,
9396 opcode: u5 = 0b01101,
9397 decoded17: u5 = 0b10000,
9398 sz: Sz,
9399 o2: u1 = 0b1,
9400 decoded24: u5 = 0b01110,
9401 U: std.builtin.Signedness = .unsigned,
9402 Q: Q,
9403 decoded31: u1 = 0b0,
9404 };
9405
9406 /// C7.2.139 FNEG (vector)
9407 pub const Fneg = packed struct {
9408 Rd: Register.Encoded,
9409 Rn: Register.Encoded,
9410 decoded10: u2 = 0b10,
9411 opcode: u5 = 0b01111,
9412 decoded17: u5 = 0b10000,
9413 sz: Sz,
9414 o2: u1 = 0b1,
9415 decoded24: u5 = 0b01110,
9416 U: std.builtin.Signedness = .unsigned,
9417 Q: Q,
9418 decoded31: u1 = 0b0,
9419 };
9420
9421 /// C7.2.157 FRINTI (vector)
9422 pub const Frinti = packed struct {
9423 Rd: Register.Encoded,
9424 Rn: Register.Encoded,
9425 decoded10: u2 = 0b10,
9426 opcode: u5 = 0b11001,
9427 decoded17: u5 = 0b10000,
9428 sz: Sz,
9429 o2: u1 = 0b1,
9430 decoded24: u5 = 0b01110,
9431 U: std.builtin.Signedness = .unsigned,
9432 Q: Q,
9433 decoded31: u1 = 0b0,
9434 };
9435
9436 /// C7.2.86 FCVTPU (vector)
9437 pub const Fcvtpu = packed struct {
9438 Rd: Register.Encoded,
9439 Rn: Register.Encoded,
9440 decoded10: u2 = 0b10,
9441 opcode: u5 = 0b11010,
9442 decoded17: u5 = 0b10000,
9443 sz: Sz,
9444 o2: u1 = 0b1,
9445 decoded24: u5 = 0b01110,
9446 U: std.builtin.Signedness = .unsigned,
9447 Q: Q,
9448 decoded31: u1 = 0b0,
9449 };
9450
9451 /// C7.2.94 FCVTZU (vector, integer)
9452 pub const Fcvtzu = packed struct {
9453 Rd: Register.Encoded,
9454 Rn: Register.Encoded,
9455 decoded10: u2 = 0b10,
9456 opcode: u5 = 0b11011,
9457 decoded17: u5 = 0b10000,
9458 sz: Sz,
9459 o2: u1 = 0b1,
9460 decoded24: u5 = 0b01110,
9461 U: std.builtin.Signedness = .unsigned,
9462 Q: Q,
9463 decoded31: u1 = 0b0,
9464 };
9465
9466 /// C7.2.169 FRSQRTE
9467 pub const Frsqrte = packed struct {
9468 Rd: Register.Encoded,
9469 Rn: Register.Encoded,
9470 decoded10: u2 = 0b10,
9471 opcode: u5 = 0b11101,
9472 decoded17: u5 = 0b10000,
9473 sz: Sz,
9474 o2: u1 = 0b1,
9475 decoded24: u5 = 0b01110,
9476 U: std.builtin.Signedness = .unsigned,
9477 Q: Q,
9478 decoded31: u1 = 0b0,
9479 };
9480
9481 /// C7.2.171 FSQRT (vector)
9482 pub const Fsqrt = packed struct {
9483 Rd: Register.Encoded,
9484 Rn: Register.Encoded,
9485 decoded10: u2 = 0b10,
9486 opcode: u5 = 0b11111,
9487 decoded17: u5 = 0b10000,
9488 sz: Sz,
9489 o2: u1 = 0b1,
9490 decoded24: u5 = 0b01110,
9491 U: std.builtin.Signedness = .unsigned,
9492 Q: Q,
9493 decoded31: u1 = 0b0,
9494 };
9495
9496 pub const Decoded = union(enum) {
9497 unallocated,
9498 suqadd: Suqadd,
9499 cnt: Cnt,
9500 sqabs: Sqabs,
9501 cmgt: Cmgt,
9502 cmeq: Cmeq,
9503 cmlt: Cmlt,
9504 abs: Abs,
9505 sqxtn: Sqxtn,
9506 frintn: Frintn,
9507 frintm: Frintm,
9508 fcvtns: Fcvtns,
9509 fcvtms: Fcvtms,
9510 fcvtas: Fcvtas,
9511 scvtf: Scvtf,
9512 fcmgt: Fcmgt,
9513 fcmeq: Fcmeq,
9514 fcmlt: Fcmlt,
9515 fabs: Fabs,
9516 frintp: Frintp,
9517 frintz: Frintz,
9518 fcvtps: Fcvtps,
9519 fcvtzs: Fcvtzs,
9520 frecpe: Frecpe,
9521 usqadd: Usqadd,
9522 sqneg: Sqneg,
9523 cmge: Cmge,
9524 cmle: Cmle,
9525 neg: Neg,
9526 sqxtun: Sqxtun,
9527 uqxtn: Uqxtn,
9528 fcvtxn: Fcvtxn,
9529 frinta: Frinta,
9530 frintx: Frintx,
9531 fcvtnu: Fcvtnu,
9532 fcvtmu: Fcvtmu,
9533 fcvtau: Fcvtau,
9534 ucvtf: Ucvtf,
9535 not: Not,
9536 fcmge: Fcmge,
9537 fcmle: Fcmle,
9538 fneg: Fneg,
9539 frinti: Frinti,
9540 fcvtpu: Fcvtpu,
9541 fcvtzu: Fcvtzu,
9542 frsqrte: Frsqrte,
9543 fsqrt: Fsqrt,
9544 };
9545 pub fn decode(inst: @This()) @This().Decoded {
9546 return switch (inst.group.U) {
9547 .signed => switch (inst.group.opcode) {
9548 else => .unallocated,
9549 0b00011 => .{ .suqadd = inst.suqadd },
9550 0b00101 => .{ .cnt = inst.cnt },
9551 0b00111 => .{ .sqabs = inst.sqabs },
9552 0b01000 => .{ .cmgt = inst.cmgt },
9553 0b01001 => .{ .cmeq = inst.cmeq },
9554 0b01010 => .{ .cmlt = inst.cmlt },
9555 0b01011 => .{ .abs = inst.abs },
9556 0b10100 => .{ .sqxtn = inst.sqxtn },
9557 0b11000 => switch (inst.group.size) {
9558 .byte, .half => .{ .frintn = inst.frintn },
9559 .single, .double => .{ .frintp = inst.frintp },
9560 },
9561 0b11001 => switch (inst.group.size) {
9562 .byte, .half => .{ .frintm = inst.frintm },
9563 .single, .double => .{ .frintz = inst.frintz },
9564 },
9565 0b11010 => switch (inst.group.size) {
9566 .byte, .half => .{ .fcvtns = inst.fcvtns },
9567 .single, .double => .{ .fcvtps = inst.fcvtps },
9568 },
9569 0b11011 => switch (inst.group.size) {
9570 .byte, .half => .{ .fcvtms = inst.fcvtms },
9571 .single, .double => .{ .fcvtzs = inst.fcvtzs },
9572 },
9573 0b11100 => switch (inst.group.size) {
9574 .byte, .half => .{ .fcvtas = inst.fcvtas },
9575 .single, .double => .unallocated,
9576 },
9577 0b11101 => switch (inst.group.size) {
9578 .byte, .half => .{ .scvtf = inst.scvtf },
9579 .single, .double => .{ .frecpe = inst.frecpe },
9580 },
9581 0b01100 => switch (inst.group.size) {
9582 .byte, .half => .unallocated,
9583 .single, .double => .{ .fcmgt = inst.fcmgt },
9584 },
9585 0b01101 => switch (inst.group.size) {
9586 .byte, .half => .unallocated,
9587 .single, .double => .{ .fcmeq = inst.fcmeq },
9588 },
9589 0b01110 => switch (inst.group.size) {
9590 .byte, .half => .unallocated,
9591 .single, .double => .{ .fcmlt = inst.fcmlt },
9592 },
9593 0b01111 => switch (inst.group.size) {
9594 .byte, .half => .unallocated,
9595 .single, .double => .{ .fabs = inst.fabs },
9596 },
9597 },
9598 .unsigned => switch (inst.group.opcode) {
9599 else => .unallocated,
9600 0b00011 => .{ .usqadd = inst.usqadd },
9601 0b00111 => .{ .sqneg = inst.sqneg },
9602 0b01000 => .{ .cmge = inst.cmge },
9603 0b01001 => .{ .cmle = inst.cmle },
9604 0b01011 => .{ .neg = inst.neg },
9605 0b10010 => .{ .sqxtun = inst.sqxtun },
9606 0b10100 => .{ .uqxtn = inst.uqxtn },
9607 0b10110 => switch (inst.group.size) {
9608 .byte, .half => .{ .fcvtxn = inst.fcvtxn },
9609 .single, .double => .unallocated,
9610 },
9611 0b11000 => switch (inst.group.size) {
9612 .byte, .half => .{ .frinta = inst.frinta },
9613 .single, .double => .unallocated,
9614 },
9615 0b11001 => switch (inst.group.size) {
9616 .byte, .half => .{ .frintx = inst.frintx },
9617 .single, .double => .{ .frinti = inst.frinti },
9618 },
9619 0b11010 => switch (inst.group.size) {
9620 .byte, .half => .{ .fcvtnu = inst.fcvtnu },
9621 .single, .double => .{ .fcvtpu = inst.fcvtpu },
9622 },
9623 0b11011 => switch (inst.group.size) {
9624 .byte, .half => .{ .fcvtmu = inst.fcvtmu },
9625 .single, .double => .{ .fcvtzu = inst.fcvtzu },
9626 },
9627 0b11100 => switch (inst.group.size) {
9628 .byte, .half => .{ .fcvtau = inst.fcvtau },
9629 .single, .double => .unallocated,
9630 },
9631 0b11101 => switch (inst.group.size) {
9632 .byte, .half => .{ .ucvtf = inst.ucvtf },
9633 .single, .double => .{ .frsqrte = inst.frsqrte },
9634 },
9635 0b00101 => switch (inst.group.size) {
9636 .byte => .{ .not = inst.not },
9637 .half, .single, .double => .unallocated,
9638 },
9639 0b01100 => switch (inst.group.size) {
9640 .byte, .half => .unallocated,
9641 .single, .double => .{ .fcmge = inst.fcmge },
9642 },
9643 0b01101 => switch (inst.group.size) {
9644 .byte, .half => .unallocated,
9645 .single, .double => .{ .fcmle = inst.fcmle },
9646 },
9647 0b01111 => switch (inst.group.size) {
9648 .byte, .half => .unallocated,
9649 .single, .double => .{ .fneg = inst.fneg },
9650 },
9651 0b11111 => switch (inst.group.size) {
9652 .byte, .half => .unallocated,
9653 .single, .double => .{ .fsqrt = inst.fsqrt },
9654 },
9655 },
9656 };
9657 }
9658 };
9659
9660 /// Advanced SIMD across lanes
9661 pub const SimdAcrossLanes = packed union {
9662 group: @This().Group,
9663 addv: Addv,
9664
9665 pub const Group = packed struct {
9666 Rd: Register.Encoded,
9667 Rn: Register.Encoded,
9668 decoded10: u2 = 0b10,
9669 opcode: u5,
9670 decoded17: u5 = 0b11000,
9671 size: Size,
9672 decoded24: u5 = 0b01110,
9673 U: std.builtin.Signedness,
9674 Q: Q,
9675 decoded31: u1 = 0b0,
9676 };
9677
9678 /// C7.2.6 ADDV
9679 pub const Addv = packed struct {
9680 Rd: Register.Encoded,
9681 Rn: Register.Encoded,
9682 decoded10: u2 = 0b10,
9683 opcode: u5 = 0b11011,
9684 decoded17: u5 = 0b11000,
9685 size: Size,
9686 decoded24: u5 = 0b01110,
9687 U: std.builtin.Signedness = .signed,
9688 Q: Q,
9689 decoded31: u1 = 0b0,
9690 };
9691
9692 pub const Decoded = union(enum) {
9693 unallocated,
9694 addv: Addv,
9695 };
9696 pub fn decode(inst: @This()) @This().Decoded {
9697 return switch (inst.group.U) {
9698 .signed => switch (inst.group.opcode) {
9699 else => .unallocated,
9700 0b11011 => .{ .addv = inst.addv },
9701 },
9702 .unsigned => .unallocated,
9703 };
9704 }
9705 };
9706
9707 /// Advanced SIMD three same
9708 pub const SimdThreeSame = packed union {
9709 group: @This().Group,
9710 addp: Addp,
9711 @"and": And,
9712 bic: Bic,
9713 orr: Orr,
9714 orn: Orn,
9715 eor: Eor,
9716 bsl: Bsl,
9717 bit: Bit,
9718 bif: Bif,
9719
9720 pub const Group = packed struct {
9721 Rd: Register.Encoded,
9722 Rn: Register.Encoded,
9723 decoded10: u1 = 0b1,
9724 opcode: u5,
9725 Rm: Register.Encoded,
9726 decoded21: u1 = 0b1,
9727 size: Size,
9728 decoded24: u5 = 0b01110,
9729 U: std.builtin.Signedness,
9730 Q: Q,
9731 decoded31: u1 = 0b0,
9732 };
9733
9734 /// C7.2.5 ADDP (vector)
9735 pub const Addp = packed struct {
9736 Rd: Register.Encoded,
9737 Rn: Register.Encoded,
9738 decoded10: u1 = 0b1,
9739 opcode: u5 = 0b10111,
9740 Rm: Register.Encoded,
9741 decoded21: u1 = 0b1,
9742 size: Size,
9743 decoded24: u5 = 0b01110,
9744 U: std.builtin.Signedness = .signed,
9745 Q: Q,
9746 decoded31: u1 = 0b0,
9747 };
9748
9749 /// C7.2.11 AND (vector)
9750 pub const And = packed struct {
9751 Rd: Register.Encoded,
9752 Rn: Register.Encoded,
9753 decoded10: u1 = 0b1,
9754 opcode: u5 = 0b00011,
9755 Rm: Register.Encoded,
9756 decoded21: u1 = 0b1,
9757 size: Size = .byte,
9758 decoded24: u5 = 0b01110,
9759 U: std.builtin.Signedness = .signed,
9760 Q: Q,
9761 decoded31: u1 = 0b0,
9762 };
9763
9764 /// C7.2.21 BIC (vector, register)
9765 pub const Bic = packed struct {
9766 Rd: Register.Encoded,
9767 Rn: Register.Encoded,
9768 decoded10: u1 = 0b1,
9769 opcode: u5 = 0b00011,
9770 Rm: Register.Encoded,
9771 decoded21: u1 = 0b1,
9772 size: Size = .half,
9773 decoded24: u5 = 0b01110,
9774 U: std.builtin.Signedness = .signed,
9775 Q: Q,
9776 decoded31: u1 = 0b0,
9777 };
9778
9779 /// C7.2.213 ORR (vector, register)
9780 pub const Orr = packed struct {
9781 Rd: Register.Encoded,
9782 Rn: Register.Encoded,
9783 decoded10: u1 = 0b1,
9784 opcode: u5 = 0b00011,
9785 Rm: Register.Encoded,
9786 decoded21: u1 = 0b1,
9787 size: Size = .single,
9788 decoded24: u5 = 0b01110,
9789 U: std.builtin.Signedness = .signed,
9790 Q: Q,
9791 decoded31: u1 = 0b0,
9792 };
9793
9794 /// C7.2.211 ORN (vector)
9795 pub const Orn = packed struct {
9796 Rd: Register.Encoded,
9797 Rn: Register.Encoded,
9798 decoded10: u1 = 0b1,
9799 opcode: u5 = 0b00011,
9800 Rm: Register.Encoded,
9801 decoded21: u1 = 0b1,
9802 size: Size = .double,
9803 decoded24: u5 = 0b01110,
9804 U: std.builtin.Signedness = .signed,
9805 Q: Q,
9806 decoded31: u1 = 0b0,
9807 };
9808
9809 /// C7.2.41 EOR (vector)
9810 pub const Eor = packed struct {
9811 Rd: Register.Encoded,
9812 Rn: Register.Encoded,
9813 decoded10: u1 = 0b1,
9814 opcode: u5 = 0b00011,
9815 Rm: Register.Encoded,
9816 decoded21: u1 = 0b1,
9817 size: Size = .byte,
9818 decoded24: u5 = 0b01110,
9819 U: std.builtin.Signedness = .unsigned,
9820 Q: Q,
9821 decoded31: u1 = 0b0,
9822 };
9823
9824 /// C7.2.24 BSL
9825 pub const Bsl = packed struct {
9826 Rd: Register.Encoded,
9827 Rn: Register.Encoded,
9828 decoded10: u1 = 0b1,
9829 opcode: u5 = 0b00011,
9830 Rm: Register.Encoded,
9831 decoded21: u1 = 0b1,
9832 size: Size = .half,
9833 decoded24: u5 = 0b01110,
9834 U: std.builtin.Signedness = .unsigned,
9835 Q: Q,
9836 decoded31: u1 = 0b0,
9837 };
9838
9839 /// C7.2.23 BIT
9840 pub const Bit = packed struct {
9841 Rd: Register.Encoded,
9842 Rn: Register.Encoded,
9843 decoded10: u1 = 0b1,
9844 opcode: u5 = 0b00011,
9845 Rm: Register.Encoded,
9846 decoded21: u1 = 0b1,
9847 size: Size = .single,
9848 decoded24: u5 = 0b01110,
9849 U: std.builtin.Signedness = .unsigned,
9850 Q: Q,
9851 decoded31: u1 = 0b0,
9852 };
9853
9854 /// C7.2.22 BIF
9855 pub const Bif = packed struct {
9856 Rd: Register.Encoded,
9857 Rn: Register.Encoded,
9858 decoded10: u1 = 0b1,
9859 opcode: u5 = 0b00011,
9860 Rm: Register.Encoded,
9861 decoded21: u1 = 0b1,
9862 size: Size = .double,
9863 decoded24: u5 = 0b01110,
9864 U: std.builtin.Signedness = .unsigned,
9865 Q: Q,
9866 decoded31: u1 = 0b0,
9867 };
9868
9869 pub const Decoded = union(enum) {
9870 unallocated,
9871 addp: Addp,
9872 @"and": And,
9873 bic: Bic,
9874 orr: Orr,
9875 orn: Orn,
9876 eor: Eor,
9877 bsl: Bsl,
9878 bit: Bit,
9879 bif: Bif,
9880 };
9881 pub fn decode(inst: @This()) @This().Decoded {
9882 return switch (inst.group.U) {
9883 .signed => switch (inst.group.opcode) {
9884 else => .unallocated,
9885 0b10111 => .{ .addp = inst.addp },
9886 0b00011 => switch (inst.group.size) {
9887 .byte => .{ .@"and" = inst.@"and" },
9888 .half => .{ .bic = inst.bic },
9889 .single => .{ .orr = inst.orr },
9890 .double => .{ .orn = inst.orn },
9891 },
9892 },
9893 .unsigned => switch (inst.group.opcode) {
9894 else => .unallocated,
9895 0b00011 => switch (inst.group.size) {
9896 .byte => .{ .eor = inst.eor },
9897 .half => .{ .bsl = inst.bsl },
9898 .single => .{ .bit = inst.bit },
9899 .double => .{ .bif = inst.bif },
9900 },
9901 },
9902 };
9903 }
9904 };
9905
9906 /// Advanced SIMD modified immediate
9907 pub const SimdModifiedImmediate = packed union {
9908 group: @This().Group,
9909 movi: Movi,
9910 orr: Orr,
9911 fmov: Fmov,
9912 mvni: Mvni,
9913 bic: Bic,
9914
9915 pub const Group = packed struct {
9916 Rd: Register.Encoded,
9917 imm5: u5,
9918 decoded10: u1 = 0b1,
9919 o2: u1,
9920 cmode: u4,
9921 imm3: u3,
9922 decoded19: u10 = 0b0111100000,
9923 op: u1,
9924 Q: Q,
9925 decoded31: u1 = 0b0,
9926 };
9927
9928 /// C7.2.204 MOVI
9929 pub const Movi = packed struct {
9930 Rd: Register.Encoded,
9931 imm5: u5,
9932 decoded10: u1 = 0b1,
9933 o2: u1 = 0b0,
9934 cmode: u4,
9935 imm3: u3,
9936 decoded19: u10 = 0b0111100000,
9937 op: u1,
9938 Q: Q,
9939 decoded31: u1 = 0b0,
9940 };
9941
9942 /// C7.2.212 ORR (vector, immediate)
9943 pub const Orr = packed struct {
9944 Rd: Register.Encoded,
9945 imm5: u5,
9946 decoded10: u1 = 0b1,
9947 o2: u1 = 0b0,
9948 cmode0: u1 = 0b1,
9949 cmode: u3,
9950 imm3: u3,
9951 decoded19: u10 = 0b0111100000,
9952 op: u1 = 0b0,
9953 Q: Q,
9954 decoded31: u1 = 0b0,
9955 };
9956
9957 /// C7.2.129 FMOV (vector, immediate)
9958 pub const Fmov = packed struct {
9959 Rd: Register.Encoded,
9960 imm5: u5,
9961 decoded10: u1 = 0b1,
9962 o2: u1,
9963 cmode: u4 = 0b1111,
9964 imm3: u3,
9965 decoded19: u10 = 0b0111100000,
9966 op: u1,
9967 Q: Q,
9968 decoded31: u1 = 0b0,
9969 };
9970
9971 /// C7.2.208 MVNI
9972 pub const Mvni = packed struct {
9973 Rd: Register.Encoded,
9974 imm5: u5,
9975 decoded10: u1 = 0b1,
9976 o2: u1 = 0b0,
9977 cmode: u4,
9978 imm3: u3,
9979 decoded19: u10 = 0b0111100000,
9980 op: u1 = 0b1,
9981 Q: Q,
9982 decoded31: u1 = 0b0,
9983 };
9984
9985 /// C7.2.20 BIC (vector, immediate)
9986 pub const Bic = packed struct {
9987 Rd: Register.Encoded,
9988 imm5: u5,
9989 decoded10: u1 = 0b1,
9990 o2: u1 = 0b0,
9991 cmode0: u1 = 0b1,
9992 cmode: u3,
9993 imm3: u3,
9994 decoded19: u10 = 0b0111100000,
9995 op: u1 = 0b1,
9996 Q: Q,
9997 decoded31: u1 = 0b0,
9998 };
9999
10000 pub const Decoded = union(enum) {
10001 unallocated,
10002 fmov: Fmov,
10003 };
10004 pub fn decode(inst: @This()) @This().Decoded {
10005 return switch (inst.group.cmode) {
10006 else => .unallocated,
10007 0b1111 => switch (inst.group.op) {
10008 0b0 => .{ .fmov = inst.fmov },
10009 0b1 => switch (inst.group.Q) {
10010 .double => .unallocated,
10011 .quad => switch (inst.group.o2) {
10012 0b1 => .unallocated,
10013 0b0 => .{ .fmov = inst.fmov },
10014 },
10015 },
10016 },
10017 };
10018 }
10019 };
10020
10021 /// Conversion between floating-point and fixed-point
10022 pub const ConvertFloatFixed = packed union {
10023 group: @This().Group,
10024
10025 pub const Group = packed struct {
10026 Rd: Register.Encoded,
10027 Rn: Register.Encoded,
10028 scale: u6,
10029 opcode: u3,
10030 rmode: u2,
10031 decoded21: u1 = 0b0,
10032 ptype: Ftype,
10033 decoded24: u5 = 0b11110,
10034 S: bool,
10035 decoded30: u1 = 0b0,
10036 sf: Register.GeneralSize,
10037 };
10038 };
10039
10040 /// Conversion between floating-point and integer
10041 pub const ConvertFloatInteger = packed union {
10042 group: @This().Group,
10043 fcvtns: Fcvtns,
10044 fcvtnu: Fcvtnu,
10045 scvtf: Scvtf,
10046 ucvtf: Ucvtf,
10047 fcvtas: Fcvtas,
10048 fcvtau: Fcvtau,
10049 fmov: Fmov,
10050 fcvtps: Fcvtps,
10051 fcvtpu: Fcvtpu,
10052 fcvtms: Fcvtms,
10053 fcvtmu: Fcvtmu,
10054 fcvtzs: Fcvtzs,
10055 fcvtzu: Fcvtzu,
10056 fjcvtzs: Fjcvtzs,
10057
10058 pub const Group = packed struct {
10059 Rd: Register.Encoded,
10060 Rn: Register.Encoded,
10061 decoded10: u6 = 0b000000,
10062 opcode: u3,
10063 rmode: u2,
10064 decoded21: u1 = 0b1,
10065 ptype: Ftype,
10066 decoded24: u5 = 0b11110,
10067 S: bool,
10068 decoded30: u1 = 0b0,
10069 sf: Register.GeneralSize,
10070 };
10071
10072 /// C7.2.81 FCVTNS (scalar)
10073 pub const Fcvtns = packed struct {
10074 Rd: Register.Encoded,
10075 Rn: Register.Encoded,
10076 decoded10: u6 = 0b000000,
10077 opcode: u3 = 0b000,
10078 rmode: Rmode = .n,
10079 decoded21: u1 = 0b1,
10080 ftype: Ftype,
10081 decoded24: u5 = 0b11110,
10082 S: bool = false,
10083 decoded30: u1 = 0b0,
10084 sf: Register.GeneralSize,
10085 };
10086
10087 /// C7.2.83 FCVTNU (scalar)
10088 pub const Fcvtnu = packed struct {
10089 Rd: Register.Encoded,
10090 Rn: Register.Encoded,
10091 decoded10: u6 = 0b000000,
10092 opcode: u3 = 0b001,
10093 rmode: Rmode = .n,
10094 decoded21: u1 = 0b1,
10095 ftype: Ftype,
10096 decoded24: u5 = 0b11110,
10097 S: bool = false,
10098 decoded30: u1 = 0b0,
10099 sf: Register.GeneralSize,
10100 };
10101
10102 /// C7.2.236 SCVTF (scalar, integer)
10103 pub const Scvtf = packed struct {
10104 Rd: Register.Encoded,
10105 Rn: Register.Encoded,
10106 decoded10: u6 = 0b000000,
10107 opcode: u3 = 0b010,
10108 rmode: Rmode = .n,
10109 decoded21: u1 = 0b1,
10110 ftype: Ftype,
10111 decoded24: u5 = 0b11110,
10112 S: bool = false,
10113 decoded30: u1 = 0b0,
10114 sf: Register.GeneralSize,
10115 };
10116
10117 /// C7.2.355 UCVTF (scalar, integer)
10118 pub const Ucvtf = packed struct {
10119 Rd: Register.Encoded,
10120 Rn: Register.Encoded,
10121 decoded10: u6 = 0b000000,
10122 opcode: u3 = 0b011,
10123 rmode: Rmode = .n,
10124 decoded21: u1 = 0b1,
10125 ftype: Ftype,
10126 decoded24: u5 = 0b11110,
10127 S: bool = false,
10128 decoded30: u1 = 0b0,
10129 sf: Register.GeneralSize,
10130 };
10131
10132 /// C7.2.71 FCVTAS (scalar)
10133 pub const Fcvtas = packed struct {
10134 Rd: Register.Encoded,
10135 Rn: Register.Encoded,
10136 decoded10: u6 = 0b000000,
10137 opcode: u3 = 0b100,
10138 rmode: Rmode = .n,
10139 decoded21: u1 = 0b1,
10140 ftype: Ftype,
10141 decoded24: u5 = 0b11110,
10142 S: bool = false,
10143 decoded30: u1 = 0b0,
10144 sf: Register.GeneralSize,
10145 };
10146
10147 /// C7.2.73 FCVTAU (scalar)
10148 pub const Fcvtau = packed struct {
10149 Rd: Register.Encoded,
10150 Rn: Register.Encoded,
10151 decoded10: u6 = 0b000000,
10152 opcode: u3 = 0b101,
10153 rmode: Rmode = .n,
10154 decoded21: u1 = 0b1,
10155 ftype: Ftype,
10156 decoded24: u5 = 0b11110,
10157 S: bool = false,
10158 decoded30: u1 = 0b0,
10159 sf: Register.GeneralSize,
10160 };
10161
10162 /// C7.2.131 FMOV (general)
10163 pub const Fmov = packed struct {
10164 Rd: Register.Encoded,
10165 Rn: Register.Encoded,
10166 decoded10: u6 = 0b000000,
10167 opcode: Opcode,
10168 rmode: Fmov.Rmode,
10169 decoded21: u1 = 0b1,
10170 ftype: Ftype,
10171 decoded24: u5 = 0b11110,
10172 S: bool = false,
10173 decoded30: u1 = 0b0,
10174 sf: Register.GeneralSize,
10175
10176 pub const Opcode = enum(u3) {
10177 float_to_integer = 0b110,
10178 integer_to_float = 0b111,
10179 _,
10180 };
10181
10182 pub const Rmode = enum(u2) {
10183 @"0" = 0b00,
10184 @"1" = 0b01,
10185 _,
10186 };
10187 };
10188
10189 /// C7.2.85 FCVTPS (scalar)
10190 pub const Fcvtps = packed struct {
10191 Rd: Register.Encoded,
10192 Rn: Register.Encoded,
10193 decoded10: u6 = 0b000000,
10194 opcode: u3 = 0b000,
10195 rmode: Rmode = .p,
10196 decoded21: u1 = 0b1,
10197 ftype: Ftype,
10198 decoded24: u5 = 0b11110,
10199 S: bool = false,
10200 decoded30: u1 = 0b0,
10201 sf: Register.GeneralSize,
10202 };
10203
10204 /// C7.2.87 FCVTPU (scalar)
10205 pub const Fcvtpu = packed struct {
10206 Rd: Register.Encoded,
10207 Rn: Register.Encoded,
10208 decoded10: u6 = 0b000000,
10209 opcode: u3 = 0b001,
10210 rmode: Rmode = .p,
10211 decoded21: u1 = 0b1,
10212 ftype: Ftype,
10213 decoded24: u5 = 0b11110,
10214 S: bool = false,
10215 decoded30: u1 = 0b0,
10216 sf: Register.GeneralSize,
10217 };
10218
10219 /// C7.2.76 FCVTMS (scalar)
10220 pub const Fcvtms = packed struct {
10221 Rd: Register.Encoded,
10222 Rn: Register.Encoded,
10223 decoded10: u6 = 0b000000,
10224 opcode: u3 = 0b000,
10225 rmode: Rmode = .m,
10226 decoded21: u1 = 0b1,
10227 ftype: Ftype,
10228 decoded24: u5 = 0b11110,
10229 S: bool = false,
10230 decoded30: u1 = 0b0,
10231 sf: Register.GeneralSize,
10232 };
10233
10234 /// C7.2.78 FCVTMU (scalar)
10235 pub const Fcvtmu = packed struct {
10236 Rd: Register.Encoded,
10237 Rn: Register.Encoded,
10238 decoded10: u6 = 0b000000,
10239 opcode: u3 = 0b001,
10240 rmode: Rmode = .m,
10241 decoded21: u1 = 0b1,
10242 ftype: Ftype,
10243 decoded24: u5 = 0b11110,
10244 S: bool = false,
10245 decoded30: u1 = 0b0,
10246 sf: Register.GeneralSize,
10247 };
10248
10249 /// C7.2.92 FCVTZS (scalar, integer)
10250 pub const Fcvtzs = packed struct {
10251 Rd: Register.Encoded,
10252 Rn: Register.Encoded,
10253 decoded10: u6 = 0b000000,
10254 opcode: u3 = 0b000,
10255 rmode: Rmode = .z,
10256 decoded21: u1 = 0b1,
10257 ftype: Ftype,
10258 decoded24: u5 = 0b11110,
10259 S: bool = false,
10260 decoded30: u1 = 0b0,
10261 sf: Register.GeneralSize,
10262 };
10263
10264 /// C7.2.96 FCVTZU (scalar, integer)
10265 pub const Fcvtzu = packed struct {
10266 Rd: Register.Encoded,
10267 Rn: Register.Encoded,
10268 decoded10: u6 = 0b000000,
10269 opcode: u3 = 0b001,
10270 rmode: Rmode = .z,
10271 decoded21: u1 = 0b1,
10272 ftype: Ftype,
10273 decoded24: u5 = 0b11110,
10274 S: bool = false,
10275 decoded30: u1 = 0b0,
10276 sf: Register.GeneralSize,
10277 };
10278
10279 /// C7.2.99 FJCVTZS
10280 pub const Fjcvtzs = packed struct {
10281 Rd: Register.Encoded,
10282 Rn: Register.Encoded,
10283 decoded10: u6 = 0b000000,
10284 opcode: u3 = 0b110,
10285 rmode: Rmode = .z,
10286 decoded21: u1 = 0b1,
10287 ftype: Ftype = .double,
10288 decoded24: u5 = 0b11110,
10289 S: bool = false,
10290 decoded30: u1 = 0b0,
10291 sf: Register.GeneralSize = .word,
10292 };
10293
10294 pub const Rmode = enum(u2) {
10295 /// to nearest
10296 n = 0b00,
10297 /// toward plus infinity
10298 p = 0b01,
10299 /// toward minus infinity
10300 m = 0b10,
10301 /// toward zero
10302 z = 0b11,
10303 };
10304
10305 pub const Decoded = union(enum) {
10306 unallocated,
10307 fcvtns: Fcvtns,
10308 fcvtnu: Fcvtnu,
10309 scvtf: Scvtf,
10310 ucvtf: Ucvtf,
10311 fcvtas: Fcvtas,
10312 fcvtau: Fcvtau,
10313 fmov: Fmov,
10314 fcvtps: Fcvtps,
10315 fcvtpu: Fcvtpu,
10316 fcvtms: Fcvtms,
10317 fcvtmu: Fcvtmu,
10318 fcvtzs: Fcvtzs,
10319 fcvtzu: Fcvtzu,
10320 fjcvtzs: Fjcvtzs,
10321 };
10322 pub fn decode(inst: @This()) @This().Decoded {
10323 return switch (inst.group.S) {
10324 true => .unallocated,
10325 false => switch (inst.group.ptype) {
10326 .single, .double, .half => switch (inst.group.opcode) {
10327 0b000 => switch (inst.group.rmode) {
10328 0b00 => .{ .fcvtns = inst.fcvtns },
10329 0b01 => .{ .fcvtps = inst.fcvtps },
10330 0b10 => .{ .fcvtms = inst.fcvtms },
10331 0b11 => .{ .fcvtzs = inst.fcvtzs },
10332 },
10333 0b001 => switch (inst.group.rmode) {
10334 0b00 => .{ .fcvtnu = inst.fcvtnu },
10335 0b01 => .{ .fcvtpu = inst.fcvtpu },
10336 0b10 => .{ .fcvtmu = inst.fcvtmu },
10337 0b11 => .{ .fcvtzu = inst.fcvtzu },
10338 },
10339 0b010 => switch (inst.group.rmode) {
10340 else => .unallocated,
10341 0b00 => .{ .scvtf = inst.scvtf },
10342 },
10343 0b011 => switch (inst.group.rmode) {
10344 else => .unallocated,
10345 0b00 => .{ .ucvtf = inst.ucvtf },
10346 },
10347 0b100 => switch (inst.group.rmode) {
10348 else => .unallocated,
10349 0b00 => .{ .fcvtas = inst.fcvtas },
10350 },
10351 0b101 => switch (inst.group.rmode) {
10352 else => .unallocated,
10353 0b00 => .{ .fcvtau = inst.fcvtau },
10354 },
10355 0b110 => switch (inst.group.rmode) {
10356 else => .unallocated,
10357 0b00 => .{ .fmov = inst.fmov },
10358 0b11 => switch (inst.group.ptype) {
10359 .single, .double => .unallocated,
10360 .quad => unreachable,
10361 .half => .{ .fjcvtzs = inst.fjcvtzs },
10362 },
10363 },
10364 0b111 => switch (inst.group.rmode) {
10365 else => .unallocated,
10366 0b00 => .{ .fmov = inst.fmov },
10367 },
10368 },
10369 .quad => switch (inst.group.opcode) {
10370 else => .unallocated,
10371 0b110, 0b111 => switch (inst.group.rmode) {
10372 else => .unallocated,
10373 0b01 => switch (inst.group.sf) {
10374 .word => .unallocated,
10375 .doubleword => .{ .fmov = inst.fmov },
10376 },
10377 },
10378 },
10379 },
10380 };
10381 }
10382 };
10383
10384 /// Floating-point data-processing (1 source)
10385 pub const FloatDataProcessingOneSource = packed union {
10386 group: @This().Group,
10387 fmov: Fmov,
10388 fabs: Fabs,
10389 fneg: Fneg,
10390 fsqrt: Fsqrt,
10391 fcvt: Fcvt,
10392 frintn: Frintn,
10393 frintp: Frintp,
10394 frintm: Frintm,
10395 frintz: Frintz,
10396 frinta: Frinta,
10397 frintx: Frintx,
10398 frinti: Frinti,
10399
10400 pub const Group = packed struct {
10401 Rd: Register.Encoded,
10402 Rn: Register.Encoded,
10403 decoded10: u5 = 0b10000,
10404 opcode: u6,
10405 decoded21: u1 = 0b1,
10406 ptype: Ftype,
10407 decoded24: u5 = 0b11110,
10408 S: bool,
10409 decoded30: u1 = 0b0,
10410 M: u1,
10411 };
10412
10413 /// C7.2.130 FMOV (register)
10414 pub const Fmov = packed struct {
10415 Rd: Register.Encoded,
10416 Rn: Register.Encoded,
10417 decoded10: u5 = 0b10000,
10418 opc: u2 = 0b00,
10419 decoded17: u4 = 0b0000,
10420 decoded21: u1 = 0b1,
10421 ftype: Ftype,
10422 decoded24: u5 = 0b11110,
10423 S: bool = false,
10424 decoded30: u1 = 0b0,
10425 M: u1 = 0b0,
10426 };
10427
10428 /// C7.2.46 FABS (scalar)
10429 pub const Fabs = packed struct {
10430 Rd: Register.Encoded,
10431 Rn: Register.Encoded,
10432 decoded10: u5 = 0b10000,
10433 opc: u2 = 0b01,
10434 decoded17: u4 = 0b0000,
10435 decoded21: u1 = 0b1,
10436 ftype: Ftype,
10437 decoded24: u5 = 0b11110,
10438 S: bool = false,
10439 decoded30: u1 = 0b0,
10440 M: u1 = 0b0,
10441 };
10442
10443 /// C7.2.140 FNEG (scalar)
10444 pub const Fneg = packed struct {
10445 Rd: Register.Encoded,
10446 Rn: Register.Encoded,
10447 decoded10: u5 = 0b10000,
10448 opc: u2 = 0b10,
10449 decoded17: u4 = 0b0000,
10450 decoded21: u1 = 0b1,
10451 ftype: Ftype,
10452 decoded24: u5 = 0b11110,
10453 S: bool = false,
10454 decoded30: u1 = 0b0,
10455 M: u1 = 0b0,
10456 };
10457
10458 /// C7.2.172 FSQRT (scalar)
10459 pub const Fsqrt = packed struct {
10460 Rd: Register.Encoded,
10461 Rn: Register.Encoded,
10462 decoded10: u5 = 0b10000,
10463 opc: u2 = 0b11,
10464 decoded17: u4 = 0b0000,
10465 decoded21: u1 = 0b1,
10466 ftype: Ftype,
10467 decoded24: u5 = 0b11110,
10468 S: bool = false,
10469 decoded30: u1 = 0b0,
10470 M: u1 = 0b0,
10471 };
10472
10473 /// C7.2.69 FCVT
10474 pub const Fcvt = packed struct {
10475 Rd: Register.Encoded,
10476 Rn: Register.Encoded,
10477 decoded10: u5 = 0b10000,
10478 opc: Ftype,
10479 decoded17: u4 = 0b0001,
10480 decoded21: u1 = 0b1,
10481 ftype: Ftype,
10482 decoded24: u5 = 0b11110,
10483 S: bool = false,
10484 decoded30: u1 = 0b0,
10485 M: u1 = 0b0,
10486 };
10487
10488 /// C7.2.162 FRINTN (scalar)
10489 pub const Frintn = packed struct {
10490 Rd: Register.Encoded,
10491 Rn: Register.Encoded,
10492 decoded10: u5 = 0b10000,
10493 rmode: Rmode = .n,
10494 decoded18: u3 = 0b001,
10495 decoded21: u1 = 0b1,
10496 ftype: Ftype,
10497 decoded24: u5 = 0b11110,
10498 S: bool = false,
10499 decoded30: u1 = 0b0,
10500 M: u1 = 0b0,
10501 };
10502
10503 /// C7.2.164 FRINTP (scalar)
10504 pub const Frintp = packed struct {
10505 Rd: Register.Encoded,
10506 Rn: Register.Encoded,
10507 decoded10: u5 = 0b10000,
10508 rmode: Rmode = .p,
10509 decoded18: u3 = 0b001,
10510 decoded21: u1 = 0b1,
10511 ftype: Ftype,
10512 decoded24: u5 = 0b11110,
10513 S: bool = false,
10514 decoded30: u1 = 0b0,
10515 M: u1 = 0b0,
10516 };
10517
10518 /// C7.2.160 FRINTM (scalar)
10519 pub const Frintm = packed struct {
10520 Rd: Register.Encoded,
10521 Rn: Register.Encoded,
10522 decoded10: u5 = 0b10000,
10523 rmode: Rmode = .m,
10524 decoded18: u3 = 0b001,
10525 decoded21: u1 = 0b1,
10526 ftype: Ftype,
10527 decoded24: u5 = 0b11110,
10528 S: bool = false,
10529 decoded30: u1 = 0b0,
10530 M: u1 = 0b0,
10531 };
10532
10533 /// C7.2.168 FRINTZ (scalar)
10534 pub const Frintz = packed struct {
10535 Rd: Register.Encoded,
10536 Rn: Register.Encoded,
10537 decoded10: u5 = 0b10000,
10538 rmode: Rmode = .z,
10539 decoded18: u3 = 0b001,
10540 decoded21: u1 = 0b1,
10541 ftype: Ftype,
10542 decoded24: u5 = 0b11110,
10543 S: bool = false,
10544 decoded30: u1 = 0b0,
10545 M: u1 = 0b0,
10546 };
10547
10548 /// C7.2.156 FRINTA (scalar)
10549 pub const Frinta = packed struct {
10550 Rd: Register.Encoded,
10551 Rn: Register.Encoded,
10552 decoded10: u5 = 0b10000,
10553 rmode: Rmode = .a,
10554 decoded18: u3 = 0b001,
10555 decoded21: u1 = 0b1,
10556 ftype: Ftype,
10557 decoded24: u5 = 0b11110,
10558 S: bool = false,
10559 decoded30: u1 = 0b0,
10560 M: u1 = 0b0,
10561 };
10562
10563 /// C7.2.166 FRINTX (scalar)
10564 pub const Frintx = packed struct {
10565 Rd: Register.Encoded,
10566 Rn: Register.Encoded,
10567 decoded10: u5 = 0b10000,
10568 rmode: Rmode = .x,
10569 decoded18: u3 = 0b001,
10570 decoded21: u1 = 0b1,
10571 ftype: Ftype,
10572 decoded24: u5 = 0b11110,
10573 S: bool = false,
10574 decoded30: u1 = 0b0,
10575 M: u1 = 0b0,
10576 };
10577
10578 /// C7.2.158 FRINTI (scalar)
10579 pub const Frinti = packed struct {
10580 Rd: Register.Encoded,
10581 Rn: Register.Encoded,
10582 decoded10: u5 = 0b10000,
10583 rmode: Rmode = .i,
10584 decoded18: u3 = 0b001,
10585 decoded21: u1 = 0b1,
10586 ftype: Ftype,
10587 decoded24: u5 = 0b11110,
10588 S: bool = false,
10589 decoded30: u1 = 0b0,
10590 M: u1 = 0b0,
10591 };
10592
10593 pub const Rmode = enum(u3) {
10594 /// to nearest with ties to even
10595 n = 0b000,
10596 /// toward plus infinity
10597 p = 0b001,
10598 /// toward minus infinity
10599 m = 0b010,
10600 /// toward zero
10601 z = 0b011,
10602 /// to nearest with ties to away
10603 a = 0b100,
10604 /// exact, using current rounding mode
10605 x = 0b110,
10606 /// using current rounding mode
10607 i = 0b111,
10608 _,
10609 };
10610
10611 pub const Decoded = union(enum) {
10612 unallocated,
10613 fmov: Fmov,
10614 fabs: Fabs,
10615 fneg: Fneg,
10616 fsqrt: Fsqrt,
10617 fcvt: Fcvt,
10618 frintn: Frintn,
10619 frintp: Frintp,
10620 frintm: Frintm,
10621 frintz: Frintz,
10622 frinta: Frinta,
10623 frintx: Frintx,
10624 frinti: Frinti,
10625 };
10626 pub fn decode(inst: @This()) @This().Decoded {
10627 return switch (inst.group.M) {
10628 0b0 => switch (inst.group.S) {
10629 true => .unallocated,
10630 false => switch (inst.group.ptype) {
10631 .single, .double, .half => switch (inst.group.opcode) {
10632 else => .unallocated,
10633 0b000000 => .{ .fmov = inst.fmov },
10634 0b000001 => .{ .fabs = inst.fabs },
10635 0b000010 => .{ .fneg = inst.fneg },
10636 0b000011 => .{ .fsqrt = inst.fsqrt },
10637 0b000101, 0b000111 => .{ .fcvt = inst.fcvt },
10638 0b001000 => .{ .frintn = inst.frintn },
10639 0b001001 => .{ .frintp = inst.frintp },
10640 0b001010 => .{ .frintm = inst.frintm },
10641 0b001011 => .{ .frintz = inst.frintz },
10642 0b001100 => .{ .frinta = inst.frinta },
10643 0b001110 => .{ .frintx = inst.frintx },
10644 0b001111 => .{ .frinti = inst.frinti },
10645 },
10646 .quad => .unallocated,
10647 },
10648 },
10649 0b1 => .unallocated,
10650 };
10651 }
10652 };
10653
10654 /// Floating-point compare
10655 pub const FloatCompare = packed union {
10656 group: @This().Group,
10657 fcmp: Fcmp,
10658 fcmpe: Fcmpe,
10659
10660 pub const Group = packed struct {
10661 opcode2: u5,
10662 Rn: Register.Encoded,
10663 decoded10: u4 = 0b1000,
10664 op: u2,
10665 Rm: Register.Encoded,
10666 decoded21: u1 = 0b1,
10667 ptype: Ftype,
10668 decoded24: u5 = 0b11110,
10669 S: bool,
10670 decoded30: u1 = 0b0,
10671 M: u1,
10672 };
10673
10674 /// C7.2.66 FCMP
10675 pub const Fcmp = packed struct {
10676 decoded0: u3 = 0b000,
10677 opc0: Opc0,
10678 opc1: u1 = 0b0,
10679 Rn: Register.Encoded,
10680 decoded10: u4 = 0b1000,
10681 op: u2 = 0b00,
10682 Rm: Register.Encoded,
10683 decoded21: u1 = 0b1,
10684 ftype: Ftype,
10685 decoded24: u5 = 0b11110,
10686 S: bool = false,
10687 decoded30: u1 = 0b0,
10688 M: u1 = 0b0,
10689 };
10690
10691 /// C7.2.67 FCMPE
10692 pub const Fcmpe = packed struct {
10693 decoded0: u3 = 0b000,
10694 opc0: Opc0,
10695 opc1: u1 = 0b1,
10696 Rn: Register.Encoded,
10697 decoded10: u4 = 0b1000,
10698 op: u2 = 0b00,
10699 Rm: Register.Encoded,
10700 decoded21: u1 = 0b1,
10701 ftype: Ftype,
10702 decoded24: u5 = 0b11110,
10703 S: bool = false,
10704 decoded30: u1 = 0b0,
10705 M: u1 = 0b0,
10706 };
10707
10708 pub const Opc0 = enum(u1) {
10709 register = 0b00,
10710 zero = 0b01,
10711 };
10712 };
10713
10714 /// Floating-point immediate
10715 pub const FloatImmediate = packed union {
10716 group: @This().Group,
10717 fmov: Fmov,
10718
10719 pub const Group = packed struct {
10720 Rd: Register.Encoded,
10721 imm5: u5,
10722 decoded10: u3 = 0b100,
10723 imm8: u8,
10724 decoded21: u1 = 0b1,
10725 ptype: Ftype,
10726 decoded24: u5 = 0b11110,
10727 S: bool,
10728 decoded30: u1 = 0b0,
10729 M: u1,
10730 };
10731
10732 /// C7.2.132 FMOV (scalar, immediate)
10733 pub const Fmov = packed struct {
10734 Rd: Register.Encoded,
10735 imm5: u5 = 0b00000,
10736 decoded10: u3 = 0b100,
10737 imm8: Imm8,
10738 decoded21: u1 = 0b1,
10739 ftype: Ftype,
10740 decoded24: u5 = 0b11110,
10741 S: bool = false,
10742 decoded30: u1 = 0b0,
10743 M: u1 = 0b0,
10744
10745 pub const Imm8 = packed struct(u8) {
10746 mantissa: u4,
10747 exponent: i3,
10748 sign: std.math.Sign,
10749
10750 pub const Modified = packed struct(u8) { imm5: u5, imm3: u3 };
10751
10752 pub fn fromModified(mod: Modified) Imm8 {
10753 return @bitCast(mod);
10754 }
10755
10756 pub fn toModified(imm8: Imm8) Modified {
10757 return @bitCast(imm8);
10758 }
10759
10760 pub fn decode(imm8: Imm8) f16 {
10761 const Normalized = std.math.FloatRepr(f16).Normalized;
10762 return Normalized.reconstruct(.{
10763 .fraction = @as(Normalized.Fraction, imm8.mantissa) << 6,
10764 .exponent = @as(Normalized.Exponent, imm8.exponent) + 1,
10765 }, imm8.sign);
10766 }
10767 };
10768 };
10769
10770 pub const Decoded = union(enum) {
10771 unallocated,
10772 fmov: Fmov,
10773 };
10774 pub fn decode(inst: @This()) @This().Decoded {
10775 return switch (inst.group.M) {
10776 0b0 => switch (inst.group.S) {
10777 true => .unallocated,
10778 false => switch (inst.group.imm5) {
10779 else => .unallocated,
10780 0b00000 => switch (inst.group.ptype) {
10781 .quad => .unallocated,
10782 .single, .double, .half => .{ .fmov = inst.fmov },
10783 },
10784 },
10785 },
10786 0b1 => .unallocated,
10787 };
10788 }
10789 };
10790
10791 /// Floating-point conditional compare
10792 pub const FloatConditionalCompare = packed union {
10793 group: @This().Group,
10794
10795 pub const Group = packed struct {
10796 nzcv: Nzcv,
10797 op: u1,
10798 Rn: Register.Encoded,
10799 decoded10: u2 = 0b01,
10800 cond: ConditionCode,
10801 Rm: Register.Encoded,
10802 decoded21: u1 = 0b1,
10803 ptype: Ftype,
10804 decoded24: u5 = 0b11110,
10805 S: bool,
10806 decoded30: u1 = 0b0,
10807 M: u1,
10808 };
10809 };
10810
10811 /// Floating-point data-processing (2 source)
10812 pub const FloatDataProcessingTwoSource = packed union {
10813 group: @This().Group,
10814 fmul: Fmul,
10815 fdiv: Fdiv,
10816 fadd: Fadd,
10817 fsub: Fsub,
10818 fmax: Fmax,
10819 fmin: Fmin,
10820 fmaxnm: Fmaxnm,
10821 fminnm: Fminnm,
10822 fnmul: Fnmul,
10823
10824 pub const Group = packed struct {
10825 Rd: Register.Encoded,
10826 Rn: Register.Encoded,
10827 decoded10: u2 = 0b10,
10828 opcode: Opcode,
10829 Rm: Register.Encoded,
10830 decoded21: u1 = 0b1,
10831 ptype: Ftype,
10832 decoded24: u5 = 0b11110,
10833 S: bool,
10834 decoded30: u1 = 0b0,
10835 M: u1,
10836 };
10837
10838 /// C7.2.136 FMUL (scalar)
10839 pub const Fmul = packed struct {
10840 Rd: Register.Encoded,
10841 Rn: Register.Encoded,
10842 decoded10: u2 = 0b10,
10843 opcode: Opcode = .fmul,
10844 Rm: Register.Encoded,
10845 decoded21: u1 = 0b1,
10846 ftype: Ftype,
10847 decoded24: u5 = 0b11110,
10848 S: bool = false,
10849 decoded30: u1 = 0b0,
10850 M: u1 = 0b0,
10851 };
10852
10853 /// C7.2.98 FDIV (scalar)
10854 pub const Fdiv = packed struct {
10855 Rd: Register.Encoded,
10856 Rn: Register.Encoded,
10857 decoded10: u2 = 0b10,
10858 opcode: Opcode = .fdiv,
10859 Rm: Register.Encoded,
10860 decoded21: u1 = 0b1,
10861 ftype: Ftype,
10862 decoded24: u5 = 0b11110,
10863 S: bool = false,
10864 decoded30: u1 = 0b0,
10865 M: u1 = 0b0,
10866 };
10867
10868 /// C7.2.50 FADD (scalar)
10869 pub const Fadd = packed struct {
10870 Rd: Register.Encoded,
10871 Rn: Register.Encoded,
10872 decoded10: u2 = 0b10,
10873 opcode: Opcode = .fadd,
10874 Rm: Register.Encoded,
10875 decoded21: u1 = 0b1,
10876 ftype: Ftype,
10877 decoded24: u5 = 0b11110,
10878 S: bool = false,
10879 decoded30: u1 = 0b0,
10880 M: u1 = 0b0,
10881 };
10882
10883 /// C7.2.174 FSUB (scalar)
10884 pub const Fsub = packed struct {
10885 Rd: Register.Encoded,
10886 Rn: Register.Encoded,
10887 decoded10: u2 = 0b10,
10888 opcode: Opcode = .fsub,
10889 Rm: Register.Encoded,
10890 decoded21: u1 = 0b1,
10891 ftype: Ftype,
10892 decoded24: u5 = 0b11110,
10893 S: bool = false,
10894 decoded30: u1 = 0b0,
10895 M: u1 = 0b0,
10896 };
10897
10898 /// C7.2.102 FMAX (scalar)
10899 pub const Fmax = packed struct {
10900 Rd: Register.Encoded,
10901 Rn: Register.Encoded,
10902 decoded10: u2 = 0b10,
10903 opcode: Opcode = .fmax,
10904 Rm: Register.Encoded,
10905 decoded21: u1 = 0b1,
10906 ftype: Ftype,
10907 decoded24: u5 = 0b11110,
10908 S: bool = false,
10909 decoded30: u1 = 0b0,
10910 M: u1 = 0b0,
10911 };
10912
10913 /// C7.2.112 FMIN (scalar)
10914 pub const Fmin = packed struct {
10915 Rd: Register.Encoded,
10916 Rn: Register.Encoded,
10917 decoded10: u2 = 0b10,
10918 opcode: Opcode = .fmin,
10919 Rm: Register.Encoded,
10920 decoded21: u1 = 0b1,
10921 ftype: Ftype,
10922 decoded24: u5 = 0b11110,
10923 S: bool = false,
10924 decoded30: u1 = 0b0,
10925 M: u1 = 0b0,
10926 };
10927
10928 /// C7.2.104 FMAXNM (scalar)
10929 pub const Fmaxnm = packed struct {
10930 Rd: Register.Encoded,
10931 Rn: Register.Encoded,
10932 decoded10: u2 = 0b10,
10933 opcode: Opcode = .fmaxnm,
10934 Rm: Register.Encoded,
10935 decoded21: u1 = 0b1,
10936 ftype: Ftype,
10937 decoded24: u5 = 0b11110,
10938 S: bool = false,
10939 decoded30: u1 = 0b0,
10940 M: u1 = 0b0,
10941 };
10942
10943 /// C7.2.114 FMINNM (scalar)
10944 pub const Fminnm = packed struct {
10945 Rd: Register.Encoded,
10946 Rn: Register.Encoded,
10947 decoded10: u2 = 0b10,
10948 opcode: Opcode = .fminnm,
10949 Rm: Register.Encoded,
10950 decoded21: u1 = 0b1,
10951 ftype: Ftype,
10952 decoded24: u5 = 0b11110,
10953 S: bool = false,
10954 decoded30: u1 = 0b0,
10955 M: u1 = 0b0,
10956 };
10957
10958 /// C7.2.143 FNMUL (scalar)
10959 pub const Fnmul = packed struct {
10960 Rd: Register.Encoded,
10961 Rn: Register.Encoded,
10962 decoded10: u2 = 0b10,
10963 opcode: Opcode = .fnmul,
10964 Rm: Register.Encoded,
10965 decoded21: u1 = 0b1,
10966 ftype: Ftype,
10967 decoded24: u5 = 0b11110,
10968 S: bool = false,
10969 decoded30: u1 = 0b0,
10970 M: u1 = 0b0,
10971 };
10972
10973 pub const Opcode = enum(u4) {
10974 fmul = 0b0000,
10975 fdiv = 0b0001,
10976 fadd = 0b0010,
10977 fsub = 0b0011,
10978 fmax = 0b0100,
10979 fmin = 0b0101,
10980 fmaxnm = 0b0110,
10981 fminnm = 0b0111,
10982 fnmul = 0b1000,
10983 _,
10984 };
10985 };
10986
10987 /// Floating-point conditional select
10988 pub const FloatConditionalSelect = packed union {
10989 group: @This().Group,
10990 fcsel: Fcsel,
10991
10992 pub const Group = packed struct {
10993 Rd: Register.Encoded,
10994 Rn: Register.Encoded,
10995 decoded10: u2 = 0b11,
10996 cond: ConditionCode,
10997 Rm: Register.Encoded,
10998 decoded21: u1 = 0b1,
10999 ptype: Ftype,
11000 decoded24: u5 = 0b11110,
11001 S: bool,
11002 decoded30: u1 = 0b0,
11003 M: u1,
11004 };
11005
11006 /// C7.2.68 FCSEL
11007 pub const Fcsel = packed struct {
11008 Rd: Register.Encoded,
11009 Rn: Register.Encoded,
11010 decoded10: u2 = 0b11,
11011 cond: ConditionCode,
11012 Rm: Register.Encoded,
11013 decoded21: u1 = 0b1,
11014 ftype: Ftype,
11015 decoded24: u5 = 0b11110,
11016 S: bool = false,
11017 decoded30: u1 = 0b0,
11018 M: u1 = 0b0,
11019 };
11020
11021 pub const Decoded = union(enum) {
11022 unallocated,
11023 fcsel: Fcsel,
11024 };
11025 pub fn decode(inst: @This()) @This().Decoded {
11026 return switch (inst.group.ptype) {
11027 .quad => .unallocated,
11028 .single, .double, .half => switch (inst.group.S) {
11029 true => .unallocated,
11030 false => switch (inst.group.M) {
11031 0b0 => .{ .fcsel = inst.fcsel },
11032 0b1 => .unallocated,
11033 },
11034 },
11035 };
11036 }
11037 };
11038
11039 /// Floating-point data-processing (3 source)
11040 pub const FloatDataProcessingThreeSource = packed union {
11041 group: @This().Group,
11042 fmadd: Fmadd,
11043 fmsub: Fmsub,
11044 fnmadd: Fnmadd,
11045 fnmsub: Fnmsub,
11046
11047 pub const Group = packed struct {
11048 Rd: Register.Encoded,
11049 Rn: Register.Encoded,
11050 Ra: Register.Encoded,
11051 o0: AddSubtractOp,
11052 Rm: Register.Encoded,
11053 o1: u1,
11054 ptype: Ftype,
11055 decoded24: u5 = 0b11111,
11056 S: bool,
11057 decoded30: u1 = 0b0,
11058 M: u1,
11059 };
11060
11061 /// C7.2.100 FMADD
11062 pub const Fmadd = packed struct {
11063 Rd: Register.Encoded,
11064 Rn: Register.Encoded,
11065 Ra: Register.Encoded,
11066 o0: AddSubtractOp = .add,
11067 Rm: Register.Encoded,
11068 o1: O1 = .fm,
11069 ftype: Ftype,
11070 decoded24: u5 = 0b11111,
11071 S: bool = false,
11072 decoded30: u1 = 0b0,
11073 M: u1 = 0b0,
11074 };
11075
11076 /// C7.2.133 FMSUB
11077 pub const Fmsub = packed struct {
11078 Rd: Register.Encoded,
11079 Rn: Register.Encoded,
11080 Ra: Register.Encoded,
11081 o0: AddSubtractOp = .sub,
11082 Rm: Register.Encoded,
11083 o1: O1 = .fm,
11084 ftype: Ftype,
11085 decoded24: u5 = 0b11111,
11086 S: bool = false,
11087 decoded30: u1 = 0b0,
11088 M: u1 = 0b0,
11089 };
11090
11091 /// C7.2.141 FNMADD
11092 pub const Fnmadd = packed struct {
11093 Rd: Register.Encoded,
11094 Rn: Register.Encoded,
11095 Ra: Register.Encoded,
11096 o0: AddSubtractOp = .add,
11097 Rm: Register.Encoded,
11098 o1: O1 = .fnm,
11099 ftype: Ftype,
11100 decoded24: u5 = 0b11111,
11101 S: bool = false,
11102 decoded30: u1 = 0b0,
11103 M: u1 = 0b0,
11104 };
11105
11106 /// C7.2.142 FNMSUB
11107 pub const Fnmsub = packed struct {
11108 Rd: Register.Encoded,
11109 Rn: Register.Encoded,
11110 Ra: Register.Encoded,
11111 o0: AddSubtractOp = .sub,
11112 Rm: Register.Encoded,
11113 o1: O1 = .fnm,
11114 ftype: Ftype,
11115 decoded24: u5 = 0b11111,
11116 S: bool = false,
11117 decoded30: u1 = 0b0,
11118 M: u1 = 0b0,
11119 };
11120
11121 pub const O1 = enum(u1) {
11122 fm = 0b0,
11123 fnm = 0b1,
11124 };
11125 };
11126
11127 pub const Size = enum(u2) {
11128 byte = 0b00,
11129 half = 0b01,
11130 single = 0b10,
11131 double = 0b11,
11132
11133 pub fn n(s: Size) Size {
11134 return @enumFromInt(@intFromEnum(s) - 1);
11135 }
11136
11137 pub fn w(s: Size) Size {
11138 return @enumFromInt(@intFromEnum(s) + 1);
11139 }
11140
11141 pub fn toScalarSize(s: Size) Register.ScalarSize {
11142 return switch (s) {
11143 .byte => .byte,
11144 .half => .half,
11145 .single => .single,
11146 .double => .double,
11147 };
11148 }
11149
11150 pub fn fromScalarSize(ss: Register.ScalarSize) Size {
11151 return switch (ss) {
11152 else => unreachable,
11153 .byte => .byte,
11154 .half => .half,
11155 .single => .single,
11156 .double => .double,
11157 };
11158 }
11159
11160 pub fn toSz(s: Size) Sz {
11161 return switch (s) {
11162 else => unreachable,
11163 .single => .single,
11164 .double => .double,
11165 };
11166 }
11167 };
11168
11169 pub const Sz = enum(u1) {
11170 single = 0b0,
11171 double = 0b1,
11172
11173 pub fn toScalarSize(sz: Sz) Register.ScalarSize {
11174 return switch (sz) {
11175 .single => .single,
11176 .double => .double,
11177 };
11178 }
11179
11180 pub fn fromScalarSize(ss: Register.ScalarSize) Sz {
11181 return switch (ss) {
11182 else => unreachable,
11183 .single => .single,
11184 .double => .double,
11185 };
11186 }
11187
11188 pub fn toSize(sz: Sz) Size {
11189 return switch (sz) {
11190 .single => .single,
11191 .double => .double,
11192 };
11193 }
11194 };
11195
11196 pub const Q = enum(u1) {
11197 double = 0b0,
11198 quad = 0b1,
11199 };
11200
11201 pub const Ftype = enum(u2) {
11202 single = 0b00,
11203 double = 0b01,
11204 quad = 0b10,
11205 half = 0b11,
11206
11207 pub fn toScalarSize(ftype: Ftype) Register.ScalarSize {
11208 return switch (ftype) {
11209 .single => .single,
11210 .double => .double,
11211 .quad => .quad,
11212 .half => .half,
11213 };
11214 }
11215
11216 pub fn fromScalarSize(ss: Register.ScalarSize) Ftype {
11217 return switch (ss) {
11218 else => unreachable,
11219 .single => .single,
11220 .double => .double,
11221 .quad => .quad,
11222 .half => .half,
11223 };
11224 }
11225 };
11226
11227 pub const Decoded = union(enum) {
11228 unallocated,
11229 simd_scalar_copy: SimdScalarCopy,
11230 simd_scalar_two_register_miscellaneous_fp16: SimdScalarTwoRegisterMiscellaneousFp16,
11231 simd_scalar_two_register_miscellaneous: SimdScalarTwoRegisterMiscellaneous,
11232 simd_scalar_pairwise: SimdScalarPairwise,
11233 simd_copy: SimdCopy,
11234 simd_two_register_miscellaneous_fp16: SimdTwoRegisterMiscellaneousFp16,
11235 simd_two_register_miscellaneous: SimdTwoRegisterMiscellaneous,
11236 simd_across_lanes: SimdAcrossLanes,
11237 simd_three_same: SimdThreeSame,
11238 simd_modified_immediate: SimdModifiedImmediate,
11239 convert_float_fixed: ConvertFloatFixed,
11240 convert_float_integer: ConvertFloatInteger,
11241 float_data_processing_one_source: FloatDataProcessingOneSource,
11242 float_compare: FloatCompare,
11243 float_immediate: FloatImmediate,
11244 float_conditional_compare: FloatConditionalCompare,
11245 float_data_processing_two_source: FloatDataProcessingTwoSource,
11246 float_conditional_select: FloatConditionalSelect,
11247 float_data_processing_three_source: FloatDataProcessingThreeSource,
11248 };
11249 pub fn decode(inst: @This()) @This().Decoded {
11250 return switch (inst.group.op0) {
11251 else => .unallocated,
11252 0b0101, 0b0111 => switch (inst.group.op1) {
11253 0b00...0b01 => if (inst.group.op3 & 0b000100001 == 0b000000001)
11254 if (inst.group.op1 == 0b00 and inst.group.op2 & 0b1100 == 0b0000)
11255 .{ .simd_scalar_copy = inst.simd_scalar_copy }
11256 else
11257 .unallocated
11258 else if (inst.group.op3 & 0b110000011 == 0b000000010) switch (inst.group.op2) {
11259 else => .unallocated,
11260 0b1111 => .{ .simd_scalar_two_register_miscellaneous_fp16 = inst.simd_scalar_two_register_miscellaneous_fp16 },
11261 0b0100, 0b1100 => .{ .simd_scalar_two_register_miscellaneous = inst.simd_scalar_two_register_miscellaneous },
11262 0b0110, 0b1110 => .{ .simd_scalar_pairwise = inst.simd_scalar_pairwise },
11263 } else .unallocated,
11264 0b10, 0b11 => switch (@as(u1, @truncate(inst.group.op3 >> 0))) {
11265 0b1 => switch (inst.group.op1) {
11266 0b10 => .unallocated,
11267 else => .unallocated,
11268 },
11269 0b0 => .unallocated,
11270 },
11271 },
11272 0b0000, 0b0010, 0b0100, 0b0110 => if (inst.group.op1 == 0b00 and inst.group.op2 & 0b1100 == 0b0000 and inst.group.op3 & 0b000100001 == 0b0000000001)
11273 .{ .simd_copy = inst.simd_copy }
11274 else if (inst.group.op1 & 0b10 == 0b00 and inst.group.op2 == 0b1111 and inst.group.op3 & 0b110000011 == 0b000000010)
11275 .{ .simd_two_register_miscellaneous_fp16 = inst.simd_two_register_miscellaneous_fp16 }
11276 else if (inst.group.op1 & 0b10 == 0b00 and inst.group.op2 & 0b0111 == 0b0100 and inst.group.op3 & 0b110000011 == 0b000000010)
11277 .{ .simd_two_register_miscellaneous = inst.simd_two_register_miscellaneous }
11278 else if (inst.group.op1 & 0b10 == 0b00 and inst.group.op2 & 0b0111 == 0b0110 and inst.group.op3 & 0b110000011 == 0b000000010)
11279 .{ .simd_across_lanes = inst.simd_across_lanes }
11280 else if (inst.group.op1 & 0b10 == 0b00 and inst.group.op2 & 0b0100 == 0b0100 and inst.group.op3 & 0b000000001 == 0b000000001)
11281 .{ .simd_three_same = inst.simd_three_same }
11282 else if (inst.group.op1 == 0b10 and inst.group.op2 == 0b0000 and inst.group.op3 & 0b000000001 == 0b000000001)
11283 .{ .simd_modified_immediate = inst.simd_modified_immediate }
11284 else
11285 .unallocated,
11286 0b0001, 0b0011, 0b1001, 0b1011 => switch (@as(u1, @truncate(inst.group.op1 >> 1))) {
11287 0b0 => switch (@as(u1, @truncate(inst.group.op2 >> 2))) {
11288 0b0 => .{ .convert_float_fixed = inst.convert_float_fixed },
11289 0b1 => switch (@ctz(inst.group.op3)) {
11290 else => .{ .convert_float_integer = inst.convert_float_integer },
11291 4 => .{ .float_data_processing_one_source = inst.float_data_processing_one_source },
11292 3 => .{ .float_compare = inst.float_compare },
11293 2 => .{ .float_immediate = inst.float_immediate },
11294 1 => .{ .float_data_processing_two_source = inst.float_data_processing_two_source },
11295 0 => switch (@as(u1, @truncate(inst.group.op3 >> 1))) {
11296 0b0 => .unallocated,
11297 0b1 => .{ .float_conditional_select = inst.float_conditional_select },
11298 },
11299 },
11300 },
11301 0b1 => .unallocated,
11302 },
11303 };
11304 }
11305 };
11306
11307 pub const AddSubtractOp = enum(u1) {
11308 add = 0b0,
11309 sub = 0b1,
11310 };
11311
11312 pub const LogicalOpc = enum(u2) {
11313 @"and" = 0b00,
11314 orr = 0b01,
11315 eor = 0b10,
11316 ands = 0b11,
11317 };
11318
11319 pub const Nzcv = packed struct { v: bool, c: bool, z: bool, n: bool };
11320
11321 pub const Decoded = union(enum) {
11322 unallocated,
11323 reserved: Reserved,
11324 sme: Sme,
11325 sve: Sve,
11326 data_processing_immediate: DataProcessingImmediate,
11327 branch_exception_generating_system: BranchExceptionGeneratingSystem,
11328 load_store: LoadStore,
11329 data_processing_register: DataProcessingRegister,
11330 data_processing_vector: DataProcessingVector,
11331 };
11332 pub fn decode(inst: @This()) @This().Decoded {
11333 return switch (inst.group.op1) {
11334 0b0000 => switch (inst.group.op0) {
11335 0b0 => .{ .reserved = inst.reserved },
11336 0b1 => .{ .sme = inst.sme },
11337 },
11338 0b0001 => .unallocated,
11339 0b0010 => .{ .sve = inst.sve },
11340 0b0011 => .unallocated,
11341 0b1000, 0b1001 => .{ .data_processing_immediate = inst.data_processing_immediate },
11342 0b1010, 0b1011 => .{ .branch_exception_generating_system = inst.branch_exception_generating_system },
11343 0b0100, 0b0110, 0b1100, 0b1110 => .{ .load_store = inst.load_store },
11344 0b0101, 0b1101 => .{ .data_processing_register = inst.data_processing_register },
11345 0b0111, 0b1111 => .{ .data_processing_vector = inst.data_processing_vector },
11346 };
11347 }
11348
11349 /// C7.2.1 ABS
11350 pub fn abs(d: Register, n: Register) Instruction {
11351 switch (d.format) {
11352 else => unreachable,
11353 .scalar => |elem_size| {
11354 assert(elem_size == .double and elem_size == n.format.scalar);
11355 return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
11356 .abs = .{
11357 .Rd = d.alias.encode(.{ .V = true }),
11358 .Rn = n.alias.encode(.{ .V = true }),
11359 .size = .fromScalarSize(elem_size),
11360 },
11361 } } };
11362 },
11363 .vector => |arrangement| {
11364 assert(arrangement != .@"1d" and n.format.vector == arrangement);
11365 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
11366 .abs = .{
11367 .Rd = d.alias.encode(.{ .V = true }),
11368 .Rn = n.alias.encode(.{ .V = true }),
11369 .size = arrangement.elemSize(),
11370 .Q = arrangement.size(),
11371 },
11372 } } };
11373 },
11374 }
11375 }
11376 /// C6.2.1 ADC
11377 pub fn adc(d: Register, n: Register, m: Register) Instruction {
11378 const sf = d.format.general;
11379 assert(n.format.general == sf and m.format.general == sf);
11380 return .{ .data_processing_register = .{ .add_subtract_with_carry = .{
11381 .adc = .{
11382 .Rd = d.alias.encode(.{}),
11383 .Rn = n.alias.encode(.{}),
11384 .Rm = m.alias.encode(.{}),
11385 .sf = sf,
11386 },
11387 } } };
11388 }
11389 /// C6.2.2 ADCS
11390 pub fn adcs(d: Register, n: Register, m: Register) Instruction {
11391 const sf = d.format.general;
11392 assert(n.format.general == sf and m.format.general == sf);
11393 return .{ .data_processing_register = .{ .add_subtract_with_carry = .{
11394 .adcs = .{
11395 .Rd = d.alias.encode(.{}),
11396 .Rn = n.alias.encode(.{}),
11397 .Rm = m.alias.encode(.{}),
11398 .sf = sf,
11399 },
11400 } } };
11401 }
11402 /// C6.2.3 ADD (extended register)
11403 /// C6.2.4 ADD (immediate)
11404 /// C6.2.5 ADD (shifted register)
11405 pub fn add(d: Register, n: Register, form: union(enum) {
11406 extended_register_explicit: struct {
11407 register: Register,
11408 option: DataProcessingRegister.AddSubtractExtendedRegister.Option,
11409 amount: DataProcessingRegister.AddSubtractExtendedRegister.Extend.Amount,
11410 },
11411 extended_register: struct { register: Register, extend: DataProcessingRegister.AddSubtractExtendedRegister.Extend },
11412 immediate: u12,
11413 shifted_immediate: struct { immediate: u12, lsl: DataProcessingImmediate.AddSubtractImmediate.Shift = .@"0" },
11414 register: Register,
11415 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
11416 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
11417 }) Instruction {
11418 const sf = d.format.general;
11419 assert(n.format.general == sf);
11420 form: switch (form) {
11421 .extended_register_explicit => |extended_register_explicit| {
11422 assert(extended_register_explicit.register.format.general == switch (sf) {
11423 .word => .word,
11424 .doubleword => extended_register_explicit.option.sf(),
11425 });
11426 return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
11427 .add = .{
11428 .Rd = d.alias.encode(.{ .sp = true }),
11429 .Rn = n.alias.encode(.{ .sp = true }),
11430 .imm3 = switch (extended_register_explicit.amount) {
11431 0...4 => |amount| amount,
11432 else => unreachable,
11433 },
11434 .option = extended_register_explicit.option,
11435 .Rm = extended_register_explicit.register.alias.encode(.{}),
11436 .sf = sf,
11437 },
11438 } } };
11439 },
11440 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
11441 .register = extended_register.register,
11442 .option = extended_register.extend,
11443 .amount = switch (extended_register.extend) {
11444 .uxtb, .uxth, .uxtw, .uxtx, .sxtb, .sxth, .sxtw, .sxtx => |amount| amount,
11445 },
11446 } },
11447 .immediate => |immediate| continue :form .{ .shifted_immediate = .{ .immediate = immediate } },
11448 .shifted_immediate => |shifted_immediate| {
11449 return .{ .data_processing_immediate = .{ .add_subtract_immediate = .{
11450 .add = .{
11451 .Rd = d.alias.encode(.{ .sp = true }),
11452 .Rn = n.alias.encode(.{ .sp = true }),
11453 .imm12 = shifted_immediate.immediate,
11454 .sh = shifted_immediate.lsl,
11455 .sf = sf,
11456 },
11457 } } };
11458 },
11459 .register => |register| continue :form if (d.alias == .sp or n.alias == .sp or register.alias == .sp)
11460 .{ .extended_register = .{ .register = register, .extend = switch (sf) {
11461 .word => .{ .uxtw = 0 },
11462 .doubleword => .{ .uxtx = 0 },
11463 } } }
11464 else
11465 .{ .shifted_register = .{ .register = register } },
11466 .shifted_register_explicit => |shifted_register_explicit| {
11467 assert(shifted_register_explicit.register.format.general == sf);
11468 return .{ .data_processing_register = .{ .add_subtract_shifted_register = .{
11469 .add = .{
11470 .Rd = d.alias.encode(.{}),
11471 .Rn = n.alias.encode(.{}),
11472 .imm6 = switch (sf) {
11473 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
11474 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
11475 },
11476 .Rm = shifted_register_explicit.register.alias.encode(.{}),
11477 .shift = switch (shifted_register_explicit.shift) {
11478 .lsl, .lsr, .asr => |shift| shift,
11479 .ror => unreachable,
11480 },
11481 .sf = sf,
11482 },
11483 } } };
11484 },
11485 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
11486 .register = shifted_register.register,
11487 .shift = shifted_register.shift,
11488 .amount = switch (shifted_register.shift) {
11489 .lsl, .lsr, .asr => |amount| amount,
11490 .ror => unreachable,
11491 },
11492 } },
11493 }
11494 }
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 }
11507 /// C7.2.4 ADDP (scalar)
11508 /// C7.2.5 ADDP (vector)
11509 pub fn addp(d: Register, n: Register, form: union(enum) {
11510 scalar,
11511 vector: Register,
11512 }) Instruction {
11513 switch (form) {
11514 .scalar => {
11515 assert(d.format.scalar == .double and n.format.vector == .@"2d");
11516 return .{ .data_processing_vector = .{ .simd_scalar_pairwise = .{
11517 .addp = .{
11518 .Rd = d.alias.encode(.{ .V = true }),
11519 .Rn = n.alias.encode(.{ .V = true }),
11520 .size = .double,
11521 },
11522 } } };
11523 },
11524 .vector => |m| {
11525 const arrangement = d.format.vector;
11526 assert(arrangement != .@"1d" and n.format.vector == arrangement and m.format.vector == arrangement);
11527 return .{ .data_processing_vector = .{ .simd_three_same = .{
11528 .addp = .{
11529 .Rd = d.alias.encode(.{ .V = true }),
11530 .Rn = n.alias.encode(.{ .V = true }),
11531 .Rm = m.alias.encode(.{ .V = true }),
11532 .size = arrangement.elemSize(),
11533 .Q = arrangement.size(),
11534 },
11535 } } };
11536 },
11537 }
11538 }
11539 /// C6.2.7 ADDS (extended register)
11540 /// C6.2.8 ADDS (immediate)
11541 /// C6.2.9 ADDS (shifted register)
11542 pub fn adds(d: Register, n: Register, form: union(enum) {
11543 extended_register_explicit: struct {
11544 register: Register,
11545 option: DataProcessingRegister.AddSubtractExtendedRegister.Option,
11546 amount: DataProcessingRegister.AddSubtractExtendedRegister.Extend.Amount,
11547 },
11548 extended_register: struct { register: Register, extend: DataProcessingRegister.AddSubtractExtendedRegister.Extend },
11549 immediate: u12,
11550 shifted_immediate: struct { immediate: u12, lsl: DataProcessingImmediate.AddSubtractImmediate.Shift = .@"0" },
11551 register: Register,
11552 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
11553 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
11554 }) Instruction {
11555 const sf = d.format.general;
11556 assert(n.format.general == sf);
11557 form: switch (form) {
11558 .extended_register_explicit => |extended_register_explicit| {
11559 assert(extended_register_explicit.register.format.general == switch (sf) {
11560 .word => .word,
11561 .doubleword => extended_register_explicit.option.sf(),
11562 });
11563 return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
11564 .adds = .{
11565 .Rd = d.alias.encode(.{}),
11566 .Rn = n.alias.encode(.{ .sp = true }),
11567 .imm3 = switch (extended_register_explicit.amount) {
11568 0...4 => |amount| amount,
11569 else => unreachable,
11570 },
11571 .option = extended_register_explicit.option,
11572 .Rm = extended_register_explicit.register.alias.encode(.{}),
11573 .sf = sf,
11574 },
11575 } } };
11576 },
11577 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
11578 .register = extended_register.register,
11579 .option = extended_register.extend,
11580 .amount = switch (extended_register.extend) {
11581 .uxtb, .uxth, .uxtw, .uxtx, .sxtb, .sxth, .sxtw, .sxtx => |amount| amount,
11582 },
11583 } },
11584 .immediate => |immediate| continue :form .{ .shifted_immediate = .{ .immediate = immediate } },
11585 .shifted_immediate => |shifted_immediate| {
11586 return .{ .data_processing_immediate = .{ .add_subtract_immediate = .{
11587 .adds = .{
11588 .Rd = d.alias.encode(.{}),
11589 .Rn = n.alias.encode(.{ .sp = true }),
11590 .imm12 = shifted_immediate.immediate,
11591 .sh = shifted_immediate.lsl,
11592 .sf = sf,
11593 },
11594 } } };
11595 },
11596 .register => |register| continue :form if (d.alias == .sp or n.alias == .sp or register.alias == .sp)
11597 .{ .extended_register = .{ .register = register, .extend = switch (sf) {
11598 .word => .{ .uxtw = 0 },
11599 .doubleword => .{ .uxtx = 0 },
11600 } } }
11601 else
11602 .{ .shifted_register = .{ .register = register } },
11603 .shifted_register_explicit => |shifted_register_explicit| {
11604 assert(shifted_register_explicit.register.format.general == sf);
11605 return .{ .data_processing_register = .{ .add_subtract_shifted_register = .{
11606 .adds = .{
11607 .Rd = d.alias.encode(.{}),
11608 .Rn = n.alias.encode(.{}),
11609 .imm6 = switch (sf) {
11610 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
11611 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
11612 },
11613 .Rm = shifted_register_explicit.register.alias.encode(.{}),
11614 .shift = switch (shifted_register_explicit.shift) {
11615 .lsl, .lsr, .asr => |shift| shift,
11616 .ror => unreachable,
11617 },
11618 .sf = sf,
11619 },
11620 } } };
11621 },
11622 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
11623 .register = shifted_register.register,
11624 .shift = shifted_register.shift,
11625 .amount = switch (shifted_register.shift) {
11626 .lsl, .lsr, .asr => |amount| amount,
11627 .ror => unreachable,
11628 },
11629 } },
11630 }
11631 }
11632 /// C7.2.6 ADDV
11633 pub fn addv(d: Register, n: Register) Instruction {
11634 const arrangement = n.format.vector;
11635 assert(arrangement.len() > 2 and d.format.scalar == arrangement.elemSize().toScalarSize());
11636 return .{ .data_processing_vector = .{ .simd_across_lanes = .{
11637 .addv = .{
11638 .Rd = d.alias.encode(.{ .V = true }),
11639 .Rn = n.alias.encode(.{ .V = true }),
11640 .size = arrangement.elemSize(),
11641 .Q = arrangement.size(),
11642 },
11643 } } };
11644 }
11645 /// C6.2.10 ADR
11646 pub fn adr(d: Register, label: i21) Instruction {
11647 assert(d.format.general == .doubleword);
11648 return .{ .data_processing_immediate = .{ .pc_relative_addressing = .{
11649 .adr = .{
11650 .Rd = d.alias.encode(.{}),
11651 .immhi = @intCast(label >> 2),
11652 .immlo = @truncate(@as(u21, @bitCast(label))),
11653 },
11654 } } };
11655 }
11656 /// C6.2.11 ADRP
11657 pub fn adrp(d: Register, label: i33) Instruction {
11658 assert(d.format.general == .doubleword);
11659 const imm: i21 = @intCast(@shrExact(label, 12));
11660 return .{ .data_processing_immediate = .{ .pc_relative_addressing = .{
11661 .adrp = .{
11662 .Rd = d.alias.encode(.{}),
11663 .immhi = @intCast(imm >> 2),
11664 .immlo = @truncate(@as(u21, @bitCast(imm))),
11665 },
11666 } } };
11667 }
11668 /// C6.2.12 AND (immediate)
11669 /// C6.2.13 AND (shifted register)
11670 /// C7.2.11 AND (vector)
11671 pub fn @"and"(d: Register, n: Register, form: union(enum) {
11672 immediate: DataProcessingImmediate.Bitmask,
11673 register: Register,
11674 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
11675 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
11676 }) Instruction {
11677 switch (d.format) {
11678 else => unreachable,
11679 .general => |sf| {
11680 assert(n.format.general == sf);
11681 form: switch (form) {
11682 .immediate => |bitmask| {
11683 assert(bitmask.validImmediate(sf));
11684 return .{ .data_processing_immediate = .{ .logical_immediate = .{
11685 .@"and" = .{
11686 .Rd = d.alias.encode(.{ .sp = true }),
11687 .Rn = n.alias.encode(.{}),
11688 .imm = bitmask,
11689 .sf = sf,
11690 },
11691 } } };
11692 },
11693 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
11694 .shifted_register_explicit => |shifted_register_explicit| {
11695 assert(shifted_register_explicit.register.format.general == sf);
11696 return .{ .data_processing_register = .{ .logical_shifted_register = .{
11697 .@"and" = .{
11698 .Rd = d.alias.encode(.{}),
11699 .Rn = n.alias.encode(.{}),
11700 .imm6 = switch (sf) {
11701 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
11702 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
11703 },
11704 .Rm = shifted_register_explicit.register.alias.encode(.{}),
11705 .shift = shifted_register_explicit.shift,
11706 .sf = sf,
11707 },
11708 } } };
11709 },
11710 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
11711 .register = shifted_register.register,
11712 .shift = shifted_register.shift,
11713 .amount = switch (shifted_register.shift) {
11714 .lsl, .lsr, .asr, .ror => |amount| amount,
11715 },
11716 } },
11717 }
11718 },
11719 .vector => |arrangement| {
11720 const m = form.register;
11721 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
11722 return .{ .data_processing_vector = .{ .simd_three_same = .{
11723 .@"and" = .{
11724 .Rd = d.alias.encode(.{ .V = true }),
11725 .Rn = n.alias.encode(.{ .V = true }),
11726 .Rm = m.alias.encode(.{ .V = true }),
11727 .Q = arrangement.size(),
11728 },
11729 } } };
11730 },
11731 }
11732 }
11733 /// C6.2.14 ANDS (immediate)
11734 /// C6.2.15 ANDS (shifted register)
11735 pub fn ands(d: Register, n: Register, form: union(enum) {
11736 immediate: DataProcessingImmediate.Bitmask,
11737 register: Register,
11738 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
11739 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
11740 }) Instruction {
11741 const sf = d.format.general;
11742 assert(n.format.general == sf);
11743 form: switch (form) {
11744 .immediate => |bitmask| {
11745 assert(bitmask.validImmediate(sf));
11746 return .{ .data_processing_immediate = .{ .logical_immediate = .{
11747 .ands = .{
11748 .Rd = d.alias.encode(.{}),
11749 .Rn = n.alias.encode(.{}),
11750 .imm = bitmask,
11751 .sf = sf,
11752 },
11753 } } };
11754 },
11755 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
11756 .shifted_register_explicit => |shifted_register_explicit| {
11757 assert(shifted_register_explicit.register.format.general == sf);
11758 return .{ .data_processing_register = .{ .logical_shifted_register = .{
11759 .ands = .{
11760 .Rd = d.alias.encode(.{}),
11761 .Rn = n.alias.encode(.{}),
11762 .imm6 = switch (sf) {
11763 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
11764 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
11765 },
11766 .Rm = shifted_register_explicit.register.alias.encode(.{}),
11767 .shift = shifted_register_explicit.shift,
11768 .sf = sf,
11769 },
11770 } } };
11771 },
11772 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
11773 .register = shifted_register.register,
11774 .shift = shifted_register.shift,
11775 .amount = switch (shifted_register.shift) {
11776 .lsl, .lsr, .asr, .ror => |amount| amount,
11777 },
11778 } },
11779 }
11780 }
11781 /// C6.2.18 ASRV
11782 pub fn asrv(d: Register, n: Register, m: Register) Instruction {
11783 const sf = d.format.general;
11784 assert(n.format.general == sf and m.format.general == sf);
11785 return .{ .data_processing_register = .{ .data_processing_two_source = .{
11786 .asrv = .{
11787 .Rd = d.alias.encode(.{}),
11788 .Rn = n.alias.encode(.{}),
11789 .Rm = m.alias.encode(.{}),
11790 .sf = sf,
11791 },
11792 } } };
11793 }
11794 /// C6.2.24 AXFLAG
11795 pub fn axflag() Instruction {
11796 return .{ .branch_exception_generating_system = .{ .pstate = .{
11797 .axflag = .{},
11798 } } };
11799 }
11800 /// C6.2.25 B
11801 pub fn b(label: i28) Instruction {
11802 return .{ .branch_exception_generating_system = .{ .unconditional_branch_immediate = .{
11803 .b = .{ .imm26 = @intCast(@shrExact(label, 2)) },
11804 } } };
11805 }
11806 /// C6.2.26 B.cond
11807 pub fn @"b."(cond: ConditionCode, label: i21) Instruction {
11808 return .{ .branch_exception_generating_system = .{ .conditional_branch_immediate = .{
11809 .b = .{
11810 .cond = cond,
11811 .imm19 = @intCast(@shrExact(label, 2)),
11812 },
11813 } } };
11814 }
11815 /// C6.2.27 BC.cond
11816 pub fn @"bc."(cond: ConditionCode, label: i21) Instruction {
11817 return .{ .branch_exception_generating_system = .{ .conditional_branch_immediate = .{
11818 .bc = .{
11819 .cond = cond,
11820 .imm19 = @intCast(@shrExact(label, 2)),
11821 },
11822 } } };
11823 }
11824 /// C6.2.30 BFM
11825 pub fn bfm(d: Register, n: Register, bitmask: DataProcessingImmediate.Bitmask) Instruction {
11826 const sf = d.format.general;
11827 assert(n.format.general == sf and bitmask.validBitfield(sf));
11828 return .{ .data_processing_immediate = .{ .bitfield = .{
11829 .bfm = .{
11830 .Rd = d.alias.encode(.{}),
11831 .Rn = n.alias.encode(.{}),
11832 .imm = bitmask,
11833 .sf = sf,
11834 },
11835 } } };
11836 }
11837 /// C6.2.32 BIC (shifted register)
11838 /// C7.2.20 BIC (vector, immediate)
11839 /// C7.2.21 BIC (vector, register)
11840 pub fn bic(d: Register, n: Register, form: union(enum) {
11841 shifted_immediate: struct { immediate: u8, lsl: u5 = 0 },
11842 register: Register,
11843 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
11844 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
11845 }) Instruction {
11846 switch (d.format) {
11847 else => unreachable,
11848 .general => |sf| {
11849 assert(n.format.general == sf);
11850 form: switch (form) {
11851 else => unreachable,
11852 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
11853 .shifted_register_explicit => |shifted_register_explicit| {
11854 assert(shifted_register_explicit.register.format.general == sf);
11855 return .{ .data_processing_register = .{ .logical_shifted_register = .{
11856 .bic = .{
11857 .Rd = d.alias.encode(.{}),
11858 .Rn = n.alias.encode(.{}),
11859 .imm6 = switch (sf) {
11860 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
11861 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
11862 },
11863 .Rm = shifted_register_explicit.register.alias.encode(.{}),
11864 .shift = shifted_register_explicit.shift,
11865 .sf = sf,
11866 },
11867 } } };
11868 },
11869 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
11870 .register = shifted_register.register,
11871 .shift = shifted_register.shift,
11872 .amount = switch (shifted_register.shift) {
11873 .lsl, .lsr, .asr, .ror => |amount| amount,
11874 },
11875 } },
11876 }
11877 },
11878 .vector => |arrangement| switch (form) {
11879 else => unreachable,
11880 .shifted_immediate => |shifted_immediate| {
11881 assert(n.alias == d.alias and n.format.vector == arrangement);
11882 return .{ .data_processing_vector = .{ .simd_modified_immediate = .{
11883 .bic = .{
11884 .Rd = d.alias.encode(.{ .V = true }),
11885 .imm5 = @truncate(shifted_immediate.immediate >> 0),
11886 .cmode = switch (arrangement) {
11887 else => unreachable,
11888 .@"4h", .@"8h" => @as(u3, 0b100) |
11889 @as(u3, @as(u1, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0,
11890 .@"2s", .@"4s" => @as(u3, 0b000) |
11891 @as(u3, @as(u2, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0,
11892 },
11893 .imm3 = @intCast(shifted_immediate.immediate >> 5),
11894 .Q = arrangement.size(),
11895 },
11896 } } };
11897 },
11898 .register => |m| {
11899 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
11900 return .{ .data_processing_vector = .{ .simd_three_same = .{
11901 .bic = .{
11902 .Rd = d.alias.encode(.{ .V = true }),
11903 .Rn = n.alias.encode(.{ .V = true }),
11904 .Rm = m.alias.encode(.{ .V = true }),
11905 .Q = arrangement.size(),
11906 },
11907 } } };
11908 },
11909 },
11910 }
11911 }
11912 /// C6.2.33 BICS (shifted register)
11913 pub fn bics(d: Register, n: Register, form: union(enum) {
11914 register: Register,
11915 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
11916 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
11917 }) Instruction {
11918 const sf = d.format.general;
11919 assert(n.format.general == sf);
11920 form: switch (form) {
11921 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
11922 .shifted_register_explicit => |shifted_register_explicit| {
11923 assert(shifted_register_explicit.register.format.general == sf);
11924 return .{ .data_processing_register = .{ .logical_shifted_register = .{
11925 .bics = .{
11926 .Rd = d.alias.encode(.{}),
11927 .Rn = n.alias.encode(.{}),
11928 .imm6 = switch (sf) {
11929 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
11930 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
11931 },
11932 .Rm = shifted_register_explicit.register.alias.encode(.{}),
11933 .shift = shifted_register_explicit.shift,
11934 .sf = sf,
11935 },
11936 } } };
11937 },
11938 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
11939 .register = shifted_register.register,
11940 .shift = shifted_register.shift,
11941 .amount = switch (shifted_register.shift) {
11942 .lsl, .lsr, .asr, .ror => |amount| amount,
11943 },
11944 } },
11945 }
11946 }
11947 /// C7.2.22 BIF
11948 pub fn bif(d: Register, n: Register, m: Register) Instruction {
11949 const arrangement = d.format.vector;
11950 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
11951 return .{ .data_processing_vector = .{ .simd_three_same = .{
11952 .bif = .{
11953 .Rd = d.alias.encode(.{ .V = true }),
11954 .Rn = n.alias.encode(.{ .V = true }),
11955 .Rm = m.alias.encode(.{ .V = true }),
11956 .Q = arrangement.size(),
11957 },
11958 } } };
11959 }
11960 /// C7.2.23 BIT
11961 pub fn bit(d: Register, n: Register, m: Register) Instruction {
11962 const arrangement = d.format.vector;
11963 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
11964 return .{ .data_processing_vector = .{ .simd_three_same = .{
11965 .bit = .{
11966 .Rd = d.alias.encode(.{ .V = true }),
11967 .Rn = n.alias.encode(.{ .V = true }),
11968 .Rm = m.alias.encode(.{ .V = true }),
11969 .Q = arrangement.size(),
11970 },
11971 } } };
11972 }
11973 /// C7.2.24 BSL
11974 pub fn bsl(d: Register, n: Register, m: Register) Instruction {
11975 const arrangement = d.format.vector;
11976 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
11977 return .{ .data_processing_vector = .{ .simd_three_same = .{
11978 .bsl = .{
11979 .Rd = d.alias.encode(.{ .V = true }),
11980 .Rn = n.alias.encode(.{ .V = true }),
11981 .Rm = m.alias.encode(.{ .V = true }),
11982 .Q = arrangement.size(),
11983 },
11984 } } };
11985 }
11986 /// C6.2.34 BL
11987 pub fn bl(label: i28) Instruction {
11988 return .{ .branch_exception_generating_system = .{ .unconditional_branch_immediate = .{
11989 .bl = .{ .imm26 = @intCast(@shrExact(label, 2)) },
11990 } } };
11991 }
11992 /// C6.2.35 BLR
11993 pub fn blr(n: Register) Instruction {
11994 assert(n.format.general == .doubleword);
11995 return .{ .branch_exception_generating_system = .{ .unconditional_branch_register = .{
11996 .blr = .{ .Rn = n.alias.encode(.{}) },
11997 } } };
11998 }
11999 /// C6.2.37 BR
12000 pub fn br(n: Register) Instruction {
12001 assert(n.format.general == .doubleword);
12002 return .{ .branch_exception_generating_system = .{ .unconditional_branch_register = .{
12003 .br = .{ .Rn = n.alias.encode(.{}) },
12004 } } };
12005 }
12006 /// C6.2.40 BRK
12007 pub fn brk(imm: u16) Instruction {
12008 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
12009 .brk = .{ .imm16 = imm },
12010 } } };
12011 }
12012 /// C6.2.46 CBNZ
12013 pub fn cbnz(t: Register, label: i21) Instruction {
12014 return .{ .branch_exception_generating_system = .{ .compare_branch_immediate = .{
12015 .cbnz = .{
12016 .Rt = t.alias.encode(.{}),
12017 .imm19 = @intCast(@shrExact(label, 2)),
12018 .sf = t.format.general,
12019 },
12020 } } };
12021 }
12022 /// C6.2.47 CBZ
12023 pub fn cbz(t: Register, label: i21) Instruction {
12024 return .{ .branch_exception_generating_system = .{ .compare_branch_immediate = .{
12025 .cbz = .{
12026 .Rt = t.alias.encode(.{}),
12027 .imm19 = @intCast(@shrExact(label, 2)),
12028 .sf = t.format.general,
12029 },
12030 } } };
12031 }
12032 /// C6.2.48 CCMN (immediate)
12033 /// C6.2.49 CCMN (register)
12034 pub fn ccmn(
12035 n: Register,
12036 form: union(enum) { register: Register, immediate: u5 },
12037 nzcv: Nzcv,
12038 cond: ConditionCode,
12039 ) Instruction {
12040 const sf = n.format.general;
12041 switch (form) {
12042 .register => |m| {
12043 assert(m.format.general == sf);
12044 return .{ .data_processing_register = .{ .conditional_compare_register = .{
12045 .ccmn = .{
12046 .nzcv = nzcv,
12047 .Rn = n.alias.encode(.{}),
12048 .cond = cond,
12049 .Rm = m.alias.encode(.{}),
12050 .sf = sf,
12051 },
12052 } } };
12053 },
12054 .immediate => |imm| return .{ .data_processing_register = .{ .conditional_compare_immediate = .{
12055 .ccmn = .{
12056 .nzcv = nzcv,
12057 .Rn = n.alias.encode(.{}),
12058 .cond = cond,
12059 .imm5 = imm,
12060 .sf = sf,
12061 },
12062 } } },
12063 }
12064 }
12065 /// C6.2.50 CCMP (immediate)
12066 /// C6.2.51 CCMP (register)
12067 pub fn ccmp(
12068 n: Register,
12069 form: union(enum) { register: Register, immediate: u5 },
12070 nzcv: Nzcv,
12071 cond: ConditionCode,
12072 ) Instruction {
12073 const sf = n.format.general;
12074 switch (form) {
12075 .register => |m| {
12076 assert(m.format.general == sf);
12077 return .{ .data_processing_register = .{ .conditional_compare_register = .{
12078 .ccmp = .{
12079 .nzcv = nzcv,
12080 .Rn = n.alias.encode(.{}),
12081 .cond = cond,
12082 .Rm = m.alias.encode(.{}),
12083 .sf = sf,
12084 },
12085 } } };
12086 },
12087 .immediate => |imm| return .{ .data_processing_register = .{ .conditional_compare_immediate = .{
12088 .ccmp = .{
12089 .nzcv = nzcv,
12090 .Rn = n.alias.encode(.{}),
12091 .cond = cond,
12092 .imm5 = imm,
12093 .sf = sf,
12094 },
12095 } } },
12096 }
12097 }
12098 /// C6.2.52 CFINV
12099 pub fn cfinv() Instruction {
12100 return .{ .branch_exception_generating_system = .{ .pstate = .{
12101 .cfinv = .{},
12102 } } };
12103 }
12104 /// C6.2.56 CLREX
12105 pub fn clrex(imm: u4) Instruction {
12106 return .{ .branch_exception_generating_system = .{ .barriers = .{
12107 .clrex = .{
12108 .CRm = imm,
12109 },
12110 } } };
12111 }
12112 /// C6.2.57 CLS
12113 pub fn cls(d: Register, n: Register) Instruction {
12114 const sf = d.format.general;
12115 assert(n.format.general == sf);
12116 return .{ .data_processing_register = .{ .data_processing_one_source = .{
12117 .cls = .{
12118 .Rd = d.alias.encode(.{}),
12119 .Rn = n.alias.encode(.{}),
12120 .sf = sf,
12121 },
12122 } } };
12123 }
12124 /// C6.2.58 CLZ
12125 pub fn clz(d: Register, n: Register) Instruction {
12126 const sf = d.format.general;
12127 assert(n.format.general == sf);
12128 return .{ .data_processing_register = .{ .data_processing_one_source = .{
12129 .clz = .{
12130 .Rd = d.alias.encode(.{}),
12131 .Rn = n.alias.encode(.{}),
12132 .sf = sf,
12133 },
12134 } } };
12135 }
12136 /// C7.2.28 CMEQ (zero)
12137 pub fn cmeq(d: Register, n: Register, form: union(enum) { zero }) Instruction {
12138 switch (form) {
12139 .zero => switch (d.format) {
12140 else => unreachable,
12141 .scalar => |elem_size| {
12142 assert(elem_size == .double and elem_size == n.format.scalar);
12143 return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
12144 .cmeq = .{
12145 .Rd = d.alias.encode(.{ .V = true }),
12146 .Rn = n.alias.encode(.{ .V = true }),
12147 .size = .fromScalarSize(elem_size),
12148 },
12149 } } };
12150 },
12151 .vector => |arrangement| {
12152 assert(arrangement != .@"1d" and n.format.vector == arrangement);
12153 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12154 .cmeq = .{
12155 .Rd = d.alias.encode(.{ .V = true }),
12156 .Rn = n.alias.encode(.{ .V = true }),
12157 .size = arrangement.elemSize(),
12158 .Q = arrangement.size(),
12159 },
12160 } } };
12161 },
12162 },
12163 }
12164 }
12165 /// C7.2.30 CMGE (zero)
12166 pub fn cmge(d: Register, n: Register, form: union(enum) { zero }) Instruction {
12167 switch (form) {
12168 .zero => switch (d.format) {
12169 else => unreachable,
12170 .scalar => |elem_size| {
12171 assert(elem_size == .double and elem_size == n.format.scalar);
12172 return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
12173 .cmge = .{
12174 .Rd = d.alias.encode(.{ .V = true }),
12175 .Rn = n.alias.encode(.{ .V = true }),
12176 .size = .fromScalarSize(elem_size),
12177 },
12178 } } };
12179 },
12180 .vector => |arrangement| {
12181 assert(arrangement != .@"1d" and n.format.vector == arrangement);
12182 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12183 .cmge = .{
12184 .Rd = d.alias.encode(.{ .V = true }),
12185 .Rn = n.alias.encode(.{ .V = true }),
12186 .size = arrangement.elemSize(),
12187 .Q = arrangement.size(),
12188 },
12189 } } };
12190 },
12191 },
12192 }
12193 }
12194 /// C7.2.32 CMGT (zero)
12195 pub fn cmgt(d: Register, n: Register, form: union(enum) { zero }) Instruction {
12196 switch (form) {
12197 .zero => switch (d.format) {
12198 else => unreachable,
12199 .scalar => |elem_size| {
12200 assert(elem_size == .double and elem_size == n.format.scalar);
12201 return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
12202 .cmgt = .{
12203 .Rd = d.alias.encode(.{ .V = true }),
12204 .Rn = n.alias.encode(.{ .V = true }),
12205 .size = .fromScalarSize(elem_size),
12206 },
12207 } } };
12208 },
12209 .vector => |arrangement| {
12210 assert(arrangement != .@"1d" and n.format.vector == arrangement);
12211 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12212 .cmgt = .{
12213 .Rd = d.alias.encode(.{ .V = true }),
12214 .Rn = n.alias.encode(.{ .V = true }),
12215 .size = arrangement.elemSize(),
12216 .Q = arrangement.size(),
12217 },
12218 } } };
12219 },
12220 },
12221 }
12222 }
12223 /// C7.2.35 CMLE (zero)
12224 pub fn cmle(d: Register, n: Register, form: union(enum) { zero }) Instruction {
12225 switch (form) {
12226 .zero => switch (d.format) {
12227 else => unreachable,
12228 .scalar => |elem_size| {
12229 assert(elem_size == .double and elem_size == n.format.scalar);
12230 return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
12231 .cmle = .{
12232 .Rd = d.alias.encode(.{ .V = true }),
12233 .Rn = n.alias.encode(.{ .V = true }),
12234 .size = .fromScalarSize(elem_size),
12235 },
12236 } } };
12237 },
12238 .vector => |arrangement| {
12239 assert(arrangement != .@"1d" and n.format.vector == arrangement);
12240 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12241 .cmle = .{
12242 .Rd = d.alias.encode(.{ .V = true }),
12243 .Rn = n.alias.encode(.{ .V = true }),
12244 .size = arrangement.elemSize(),
12245 .Q = arrangement.size(),
12246 },
12247 } } };
12248 },
12249 },
12250 }
12251 }
12252 /// C7.2.36 CMLT (zero)
12253 pub fn cmlt(d: Register, n: Register, form: union(enum) { zero }) Instruction {
12254 switch (form) {
12255 .zero => switch (d.format) {
12256 else => unreachable,
12257 .scalar => |elem_size| {
12258 assert(elem_size == .double and elem_size == n.format.scalar);
12259 return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
12260 .cmlt = .{
12261 .Rd = d.alias.encode(.{ .V = true }),
12262 .Rn = n.alias.encode(.{ .V = true }),
12263 .size = .fromScalarSize(elem_size),
12264 },
12265 } } };
12266 },
12267 .vector => |arrangement| {
12268 assert(arrangement != .@"1d" and n.format.vector == arrangement);
12269 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12270 .cmlt = .{
12271 .Rd = d.alias.encode(.{ .V = true }),
12272 .Rn = n.alias.encode(.{ .V = true }),
12273 .size = arrangement.elemSize(),
12274 .Q = arrangement.size(),
12275 },
12276 } } };
12277 },
12278 },
12279 }
12280 }
12281 /// C7.2.38 CNT
12282 pub fn cnt(d: Register, n: Register) Instruction {
12283 const arrangement = d.format.vector;
12284 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement);
12285 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12286 .cnt = .{
12287 .Rd = d.alias.encode(.{ .V = true }),
12288 .Rn = n.alias.encode(.{ .V = true }),
12289 .size = arrangement.elemSize(),
12290 .Q = arrangement.size(),
12291 },
12292 } } };
12293 }
12294 /// C6.2.103 CSEL
12295 pub fn csel(d: Register, n: Register, m: Register, cond: ConditionCode) Instruction {
12296 const sf = d.format.general;
12297 assert(n.format.general == sf and m.format.general == sf);
12298 return .{ .data_processing_register = .{ .conditional_select = .{
12299 .csel = .{
12300 .Rd = d.alias.encode(.{}),
12301 .Rn = n.alias.encode(.{}),
12302 .cond = cond,
12303 .Rm = m.alias.encode(.{}),
12304 .sf = sf,
12305 },
12306 } } };
12307 }
12308 /// C6.2.106 CSINC
12309 pub fn csinc(d: Register, n: Register, m: Register, cond: ConditionCode) Instruction {
12310 const sf = d.format.general;
12311 assert(n.format.general == sf and m.format.general == sf);
12312 return .{ .data_processing_register = .{ .conditional_select = .{
12313 .csinc = .{
12314 .Rd = d.alias.encode(.{}),
12315 .Rn = n.alias.encode(.{}),
12316 .cond = cond,
12317 .Rm = m.alias.encode(.{}),
12318 .sf = sf,
12319 },
12320 } } };
12321 }
12322 /// C6.2.107 CSINV
12323 pub fn csinv(d: Register, n: Register, m: Register, cond: ConditionCode) Instruction {
12324 const sf = d.format.general;
12325 assert(n.format.general == sf and m.format.general == sf);
12326 return .{ .data_processing_register = .{ .conditional_select = .{
12327 .csinv = .{
12328 .Rd = d.alias.encode(.{}),
12329 .Rn = n.alias.encode(.{}),
12330 .cond = cond,
12331 .Rm = m.alias.encode(.{}),
12332 .sf = sf,
12333 },
12334 } } };
12335 }
12336 /// C6.2.108 CSNEG
12337 pub fn csneg(d: Register, n: Register, m: Register, cond: ConditionCode) Instruction {
12338 const sf = d.format.general;
12339 assert(n.format.general == sf and m.format.general == sf);
12340 return .{ .data_processing_register = .{ .conditional_select = .{
12341 .csneg = .{
12342 .Rd = d.alias.encode(.{}),
12343 .Rn = n.alias.encode(.{}),
12344 .cond = cond,
12345 .Rm = m.alias.encode(.{}),
12346 .sf = sf,
12347 },
12348 } } };
12349 }
12350 /// C6.2.110 DCPS1
12351 pub fn dcps1(imm: u16) Instruction {
12352 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
12353 .dcps1 = .{ .imm16 = imm },
12354 } } };
12355 }
12356 /// C6.2.111 DCPS2
12357 pub fn dcps2(imm: u16) Instruction {
12358 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
12359 .dcps2 = .{ .imm16 = imm },
12360 } } };
12361 }
12362 /// C6.2.112 DCPS3
12363 pub fn dcps3(imm: u16) Instruction {
12364 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
12365 .dcps3 = .{ .imm16 = imm },
12366 } } };
12367 }
12368 /// C6.2.116 DSB
12369 pub fn dsb(option: BranchExceptionGeneratingSystem.Barriers.Option) Instruction {
12370 return .{ .branch_exception_generating_system = .{ .barriers = .{
12371 .dsb = .{
12372 .CRm = option,
12373 },
12374 } } };
12375 }
12376 /// C7.2.39 DUP (element)
12377 /// C7.2.40 DUP (general)
12378 pub fn dup(d: Register, n: Register) Instruction {
12379 switch (d.format) {
12380 else => unreachable,
12381 .scalar => |elem_size| {
12382 assert(@intFromEnum(elem_size) <= @intFromEnum(Register.ScalarSize.double) and elem_size == n.format.element.size);
12383 return .{ .data_processing_vector = .{ .simd_scalar_copy = .{
12384 .dup = .{
12385 .Rd = d.alias.encode(.{ .V = true }),
12386 .Rn = n.alias.encode(.{ .V = true }),
12387 .imm5 = @shlExact(@as(u5, n.format.element.index) << 1 | @as(u5, 0b1), @intFromEnum(elem_size)),
12388 },
12389 } } };
12390 },
12391 .vector => |arrangement| {
12392 assert(arrangement != .@"1d");
12393 const elem_size = arrangement.elemSize();
12394 switch (n.format) {
12395 else => unreachable,
12396 .element => |element| {
12397 assert(elem_size.toScalarSize() == element.size);
12398 return .{ .data_processing_vector = .{ .simd_copy = .{
12399 .dup = .{
12400 .Rd = d.alias.encode(.{ .V = true }),
12401 .Rn = n.alias.encode(.{ .V = true }),
12402 .imm4 = .element,
12403 .imm5 = @shlExact(@as(u5, element.index) << 1 | @as(u5, 0b1), @intFromEnum(elem_size)),
12404 .Q = arrangement.size(),
12405 },
12406 } } };
12407 },
12408 .general => |sf| {
12409 assert(sf == @as(Register.GeneralSize, switch (elem_size) {
12410 .byte, .half, .single => .word,
12411 .double => .doubleword,
12412 }));
12413 return .{ .data_processing_vector = .{ .simd_copy = .{
12414 .dup = .{
12415 .Rd = d.alias.encode(.{ .V = true }),
12416 .Rn = n.alias.encode(.{}),
12417 .imm4 = .general,
12418 .imm5 = @shlExact(@as(u5, 0b1), @intFromEnum(elem_size)),
12419 .Q = arrangement.size(),
12420 },
12421 } } };
12422 },
12423 }
12424 },
12425 }
12426 }
12427 /// C6.2.118 EON (shifted register)
12428 pub fn eon(d: Register, n: Register, form: union(enum) {
12429 register: Register,
12430 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
12431 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
12432 }) Instruction {
12433 const sf = d.format.general;
12434 assert(n.format.general == sf);
12435 form: switch (form) {
12436 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
12437 .shifted_register_explicit => |shifted_register_explicit| {
12438 assert(shifted_register_explicit.register.format.general == sf);
12439 return .{ .data_processing_register = .{ .logical_shifted_register = .{
12440 .eon = .{
12441 .Rd = d.alias.encode(.{}),
12442 .Rn = n.alias.encode(.{}),
12443 .imm6 = switch (sf) {
12444 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
12445 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
12446 },
12447 .Rm = shifted_register_explicit.register.alias.encode(.{}),
12448 .shift = shifted_register_explicit.shift,
12449 .sf = sf,
12450 },
12451 } } };
12452 },
12453 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
12454 .register = shifted_register.register,
12455 .shift = shifted_register.shift,
12456 .amount = switch (shifted_register.shift) {
12457 .lsl, .lsr, .asr, .ror => |amount| amount,
12458 },
12459 } },
12460 }
12461 }
12462 /// C6.2.119 EOR (immediate)
12463 /// C6.2.120 EOR (shifted register)
12464 /// C7.2.41 EOR (vector)
12465 pub fn eor(d: Register, n: Register, form: union(enum) {
12466 immediate: DataProcessingImmediate.Bitmask,
12467 register: Register,
12468 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
12469 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
12470 }) Instruction {
12471 switch (d.format) {
12472 else => unreachable,
12473 .general => |sf| {
12474 assert(n.format.general == sf);
12475 form: switch (form) {
12476 .immediate => |bitmask| {
12477 assert(bitmask.validImmediate(sf));
12478 return .{ .data_processing_immediate = .{ .logical_immediate = .{
12479 .eor = .{
12480 .Rd = d.alias.encode(.{ .sp = true }),
12481 .Rn = n.alias.encode(.{}),
12482 .imm = bitmask,
12483 .sf = sf,
12484 },
12485 } } };
12486 },
12487 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
12488 .shifted_register_explicit => |shifted_register_explicit| {
12489 assert(shifted_register_explicit.register.format.general == sf);
12490 return .{ .data_processing_register = .{ .logical_shifted_register = .{
12491 .eor = .{
12492 .Rd = d.alias.encode(.{}),
12493 .Rn = n.alias.encode(.{}),
12494 .imm6 = switch (sf) {
12495 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
12496 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
12497 },
12498 .Rm = shifted_register_explicit.register.alias.encode(.{}),
12499 .shift = shifted_register_explicit.shift,
12500 .sf = sf,
12501 },
12502 } } };
12503 },
12504 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
12505 .register = shifted_register.register,
12506 .shift = shifted_register.shift,
12507 .amount = switch (shifted_register.shift) {
12508 .lsl, .lsr, .asr, .ror => |amount| amount,
12509 },
12510 } },
12511 }
12512 },
12513 .vector => |arrangement| {
12514 const m = form.register;
12515 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
12516 return .{ .data_processing_vector = .{ .simd_three_same = .{
12517 .eor = .{
12518 .Rd = d.alias.encode(.{ .V = true }),
12519 .Rn = n.alias.encode(.{ .V = true }),
12520 .Rm = m.alias.encode(.{ .V = true }),
12521 .Q = arrangement.size(),
12522 },
12523 } } };
12524 },
12525 }
12526 }
12527 /// C6.2.124 EXTR
12528 pub fn extr(d: Register, n: Register, m: Register, lsb: u6) Instruction {
12529 const sf = d.format.general;
12530 assert(n.format.general == sf and m.format.general == sf);
12531 return .{ .data_processing_immediate = .{ .extract = .{
12532 .extr = .{
12533 .Rd = d.alias.encode(.{}),
12534 .Rn = n.alias.encode(.{}),
12535 .imms = switch (sf) {
12536 .word => @as(u5, @intCast(lsb)),
12537 .doubleword => @as(u6, @intCast(lsb)),
12538 },
12539 .Rm = m.alias.encode(.{}),
12540 .N = sf,
12541 .sf = sf,
12542 },
12543 } } };
12544 }
12545 /// C7.2.45 FABS (vector)
12546 /// C7.2.46 FABS (scalar)
12547 pub fn fabs(d: Register, n: Register) Instruction {
12548 switch (d.format) {
12549 else => unreachable,
12550 .vector => |arrangement| {
12551 assert(n.format.vector == arrangement);
12552 switch (arrangement.elemSize()) {
12553 else => unreachable,
12554 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
12555 .fabs = .{
12556 .Rd = d.alias.encode(.{ .V = true }),
12557 .Rn = n.alias.encode(.{ .V = true }),
12558 .Q = arrangement.size(),
12559 },
12560 } } },
12561 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12562 .fabs = .{
12563 .Rd = d.alias.encode(.{ .V = true }),
12564 .Rn = n.alias.encode(.{ .V = true }),
12565 .sz = arrangement.elemSz(),
12566 .Q = arrangement.size(),
12567 },
12568 } } },
12569 }
12570 },
12571 .scalar => |ftype| {
12572 assert(n.format.scalar == ftype);
12573 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
12574 .fabs = .{
12575 .Rd = d.alias.encode(.{ .V = true }),
12576 .Rn = n.alias.encode(.{ .V = true }),
12577 .ftype = .fromScalarSize(ftype),
12578 },
12579 } } };
12580 },
12581 }
12582 }
12583 /// C7.2.50 FADD (scalar)
12584 pub fn fadd(d: Register, n: Register, m: Register) Instruction {
12585 const ftype = d.format.scalar;
12586 assert(n.format.scalar == ftype and m.format.scalar == ftype);
12587 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
12588 .fadd = .{
12589 .Rd = d.alias.encode(.{ .V = true }),
12590 .Rn = n.alias.encode(.{ .V = true }),
12591 .Rm = m.alias.encode(.{ .V = true }),
12592 .ftype = .fromScalarSize(ftype),
12593 },
12594 } } };
12595 }
12596 /// C7.2.57 FCMEQ (zero)
12597 pub fn fcmeq(d: Register, n: Register, form: union(enum) { zero }) Instruction {
12598 switch (form) {
12599 .zero => switch (d.format) {
12600 else => unreachable,
12601 .scalar => |ftype| switch (n.format) {
12602 else => unreachable,
12603 .scalar => |n_scalar| {
12604 assert(n_scalar == ftype);
12605 switch (ftype) {
12606 else => unreachable,
12607 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
12608 .fcmeq = .{
12609 .Rd = d.alias.encode(.{ .V = true }),
12610 .Rn = n.alias.encode(.{ .V = true }),
12611 },
12612 } } },
12613 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
12614 .fcmeq = .{
12615 .Rd = d.alias.encode(.{ .V = true }),
12616 .Rn = n.alias.encode(.{ .V = true }),
12617 .sz = .fromScalarSize(ftype),
12618 },
12619 } } },
12620 }
12621 },
12622 },
12623 .vector => |arrangement| {
12624 assert(arrangement != .@"1d" and n.format.vector == arrangement);
12625 switch (arrangement.elemSize()) {
12626 else => unreachable,
12627 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
12628 .fcmeq = .{
12629 .Rd = d.alias.encode(.{ .V = true }),
12630 .Rn = n.alias.encode(.{ .V = true }),
12631 .Q = arrangement.size(),
12632 },
12633 } } },
12634 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12635 .fcmeq = .{
12636 .Rd = d.alias.encode(.{ .V = true }),
12637 .Rn = n.alias.encode(.{ .V = true }),
12638 .sz = arrangement.elemSz(),
12639 .Q = arrangement.size(),
12640 },
12641 } } },
12642 }
12643 },
12644 },
12645 }
12646 }
12647 /// C7.2.59 FCMGE (zero)
12648 pub fn fcmge(d: Register, n: Register, form: union(enum) { zero }) Instruction {
12649 switch (form) {
12650 .zero => switch (d.format) {
12651 else => unreachable,
12652 .scalar => |ftype| switch (n.format) {
12653 else => unreachable,
12654 .scalar => |n_scalar| {
12655 assert(n_scalar == ftype);
12656 switch (ftype) {
12657 else => unreachable,
12658 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
12659 .fcmge = .{
12660 .Rd = d.alias.encode(.{ .V = true }),
12661 .Rn = n.alias.encode(.{ .V = true }),
12662 },
12663 } } },
12664 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
12665 .fcmge = .{
12666 .Rd = d.alias.encode(.{ .V = true }),
12667 .Rn = n.alias.encode(.{ .V = true }),
12668 .sz = .fromScalarSize(ftype),
12669 },
12670 } } },
12671 }
12672 },
12673 },
12674 .vector => |arrangement| {
12675 assert(arrangement != .@"1d" and n.format.vector == arrangement);
12676 switch (arrangement.elemSize()) {
12677 else => unreachable,
12678 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
12679 .fcmge = .{
12680 .Rd = d.alias.encode(.{ .V = true }),
12681 .Rn = n.alias.encode(.{ .V = true }),
12682 .Q = arrangement.size(),
12683 },
12684 } } },
12685 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12686 .fcmge = .{
12687 .Rd = d.alias.encode(.{ .V = true }),
12688 .Rn = n.alias.encode(.{ .V = true }),
12689 .sz = arrangement.elemSz(),
12690 .Q = arrangement.size(),
12691 },
12692 } } },
12693 }
12694 },
12695 },
12696 }
12697 }
12698 /// C7.2.61 FCMGT (zero)
12699 pub fn fcmgt(d: Register, n: Register, form: union(enum) { zero }) Instruction {
12700 switch (form) {
12701 .zero => switch (d.format) {
12702 else => unreachable,
12703 .scalar => |ftype| switch (n.format) {
12704 else => unreachable,
12705 .scalar => |n_scalar| {
12706 assert(n_scalar == ftype);
12707 switch (ftype) {
12708 else => unreachable,
12709 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
12710 .fcmgt = .{
12711 .Rd = d.alias.encode(.{ .V = true }),
12712 .Rn = n.alias.encode(.{ .V = true }),
12713 },
12714 } } },
12715 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
12716 .fcmgt = .{
12717 .Rd = d.alias.encode(.{ .V = true }),
12718 .Rn = n.alias.encode(.{ .V = true }),
12719 .sz = .fromScalarSize(ftype),
12720 },
12721 } } },
12722 }
12723 },
12724 },
12725 .vector => |arrangement| {
12726 assert(arrangement != .@"1d" and n.format.vector == arrangement);
12727 switch (arrangement.elemSize()) {
12728 else => unreachable,
12729 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
12730 .fcmgt = .{
12731 .Rd = d.alias.encode(.{ .V = true }),
12732 .Rn = n.alias.encode(.{ .V = true }),
12733 .Q = arrangement.size(),
12734 },
12735 } } },
12736 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12737 .fcmgt = .{
12738 .Rd = d.alias.encode(.{ .V = true }),
12739 .Rn = n.alias.encode(.{ .V = true }),
12740 .sz = arrangement.elemSz(),
12741 .Q = arrangement.size(),
12742 },
12743 } } },
12744 }
12745 },
12746 },
12747 }
12748 }
12749 /// C7.2.64 FCMLE (zero)
12750 pub fn fcmle(d: Register, n: Register, form: union(enum) { zero }) Instruction {
12751 switch (form) {
12752 .zero => switch (d.format) {
12753 else => unreachable,
12754 .scalar => |ftype| switch (n.format) {
12755 else => unreachable,
12756 .scalar => |n_scalar| {
12757 assert(n_scalar == ftype);
12758 switch (ftype) {
12759 else => unreachable,
12760 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
12761 .fcmle = .{
12762 .Rd = d.alias.encode(.{ .V = true }),
12763 .Rn = n.alias.encode(.{ .V = true }),
12764 },
12765 } } },
12766 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
12767 .fcmle = .{
12768 .Rd = d.alias.encode(.{ .V = true }),
12769 .Rn = n.alias.encode(.{ .V = true }),
12770 .sz = .fromScalarSize(ftype),
12771 },
12772 } } },
12773 }
12774 },
12775 },
12776 .vector => |arrangement| {
12777 assert(arrangement != .@"1d" and n.format.vector == arrangement);
12778 switch (arrangement.elemSize()) {
12779 else => unreachable,
12780 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
12781 .fcmle = .{
12782 .Rd = d.alias.encode(.{ .V = true }),
12783 .Rn = n.alias.encode(.{ .V = true }),
12784 .Q = arrangement.size(),
12785 },
12786 } } },
12787 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12788 .fcmle = .{
12789 .Rd = d.alias.encode(.{ .V = true }),
12790 .Rn = n.alias.encode(.{ .V = true }),
12791 .sz = arrangement.elemSz(),
12792 .Q = arrangement.size(),
12793 },
12794 } } },
12795 }
12796 },
12797 },
12798 }
12799 }
12800 /// C7.2.65 FCMLT (zero)
12801 pub fn fcmlt(d: Register, n: Register, form: union(enum) { zero }) Instruction {
12802 switch (form) {
12803 .zero => switch (d.format) {
12804 else => unreachable,
12805 .scalar => |ftype| switch (n.format) {
12806 else => unreachable,
12807 .scalar => |n_scalar| {
12808 assert(n_scalar == ftype);
12809 switch (ftype) {
12810 else => unreachable,
12811 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
12812 .fcmlt = .{
12813 .Rd = d.alias.encode(.{ .V = true }),
12814 .Rn = n.alias.encode(.{ .V = true }),
12815 },
12816 } } },
12817 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
12818 .fcmlt = .{
12819 .Rd = d.alias.encode(.{ .V = true }),
12820 .Rn = n.alias.encode(.{ .V = true }),
12821 .sz = .fromScalarSize(ftype),
12822 },
12823 } } },
12824 }
12825 },
12826 },
12827 .vector => |arrangement| {
12828 assert(arrangement != .@"1d" and n.format.vector == arrangement);
12829 switch (arrangement.elemSize()) {
12830 else => unreachable,
12831 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
12832 .fcmlt = .{
12833 .Rd = d.alias.encode(.{ .V = true }),
12834 .Rn = n.alias.encode(.{ .V = true }),
12835 .Q = arrangement.size(),
12836 },
12837 } } },
12838 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12839 .fcmlt = .{
12840 .Rd = d.alias.encode(.{ .V = true }),
12841 .Rn = n.alias.encode(.{ .V = true }),
12842 .sz = arrangement.elemSz(),
12843 .Q = arrangement.size(),
12844 },
12845 } } },
12846 }
12847 },
12848 },
12849 }
12850 }
12851 /// C7.2.66 FCMP
12852 pub fn fcmp(n: Register, form: union(enum) { register: Register, zero }) Instruction {
12853 const ftype = n.format.scalar;
12854 switch (form) {
12855 .register => |m| {
12856 assert(m.format.scalar == ftype);
12857 return .{ .data_processing_vector = .{ .float_compare = .{
12858 .fcmp = .{
12859 .opc0 = .register,
12860 .Rn = n.alias.encode(.{ .V = true }),
12861 .Rm = m.alias.encode(.{ .V = true }),
12862 .ftype = .fromScalarSize(ftype),
12863 },
12864 } } };
12865 },
12866 .zero => return .{ .data_processing_vector = .{ .float_compare = .{
12867 .fcmp = .{
12868 .opc0 = .register,
12869 .Rn = n.alias.encode(.{ .V = true }),
12870 .Rm = @enumFromInt(0b00000),
12871 .ftype = .fromScalarSize(ftype),
12872 },
12873 } } },
12874 }
12875 }
12876 /// C7.2.67 FCMPE
12877 pub fn fcmpe(n: Register, form: union(enum) { register: Register, zero }) Instruction {
12878 const ftype = n.format.scalar;
12879 switch (form) {
12880 .register => |m| {
12881 assert(m.format.scalar == ftype);
12882 return .{ .data_processing_vector = .{ .float_compare = .{
12883 .fcmpe = .{
12884 .opc0 = .zero,
12885 .Rn = n.alias.encode(.{ .V = true }),
12886 .Rm = m.alias.encode(.{ .V = true }),
12887 .ftype = .fromScalarSize(ftype),
12888 },
12889 } } };
12890 },
12891 .zero => return .{ .data_processing_vector = .{ .float_compare = .{
12892 .fcmpe = .{
12893 .opc0 = .zero,
12894 .Rn = n.alias.encode(.{ .V = true }),
12895 .Rm = @enumFromInt(0b00000),
12896 .ftype = .fromScalarSize(ftype),
12897 },
12898 } } },
12899 }
12900 }
12901 /// C7.2.68 FCSEL
12902 pub fn fcsel(d: Register, n: Register, m: Register, cond: ConditionCode) Instruction {
12903 const ftype = d.format.scalar;
12904 assert(n.format.scalar == ftype and m.format.scalar == ftype);
12905 return .{ .data_processing_vector = .{ .float_conditional_select = .{
12906 .fcsel = .{
12907 .Rd = d.alias.encode(.{ .V = true }),
12908 .Rn = n.alias.encode(.{ .V = true }),
12909 .cond = cond,
12910 .Rm = m.alias.encode(.{ .V = true }),
12911 .ftype = .fromScalarSize(ftype),
12912 },
12913 } } };
12914 }
12915 /// C7.2.69 FCVT
12916 pub fn fcvt(d: Register, n: Register) Instruction {
12917 assert(d.format.scalar != n.format.scalar);
12918 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
12919 .fcvt = .{
12920 .Rd = d.alias.encode(.{ .V = true }),
12921 .Rn = n.alias.encode(.{ .V = true }),
12922 .opc = switch (d.format.scalar) {
12923 else => unreachable,
12924 .single => .single,
12925 .double => .double,
12926 .half => .half,
12927 },
12928 .ftype = .fromScalarSize(n.format.scalar),
12929 },
12930 } } };
12931 }
12932 /// C7.2.70 FCVTAS (vector)
12933 /// C7.2.71 FCVTAS (scalar)
12934 pub fn fcvtas(d: Register, n: Register) Instruction {
12935 switch (d.format) {
12936 else => unreachable,
12937 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
12938 .fcvtas = .{
12939 .Rd = d.alias.encode(.{}),
12940 .Rn = n.alias.encode(.{ .V = true }),
12941 .ftype = .fromScalarSize(n.format.scalar),
12942 .sf = sf,
12943 },
12944 } } },
12945 .scalar => |elem_size| switch (n.format) {
12946 else => unreachable,
12947 .scalar => |ftype| {
12948 assert(ftype == elem_size);
12949 switch (elem_size) {
12950 else => unreachable,
12951 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
12952 .fcvtas = .{
12953 .Rd = d.alias.encode(.{ .V = true }),
12954 .Rn = n.alias.encode(.{ .V = true }),
12955 },
12956 } } },
12957 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
12958 .fcvtas = .{
12959 .Rd = d.alias.encode(.{ .V = true }),
12960 .Rn = n.alias.encode(.{ .V = true }),
12961 .sz = .fromScalarSize(elem_size),
12962 },
12963 } } },
12964 }
12965 },
12966 },
12967 .vector => |arrangement| {
12968 assert(arrangement != .@"1d" and n.format.vector == arrangement);
12969 switch (arrangement.elemSize()) {
12970 else => unreachable,
12971 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
12972 .fcvtas = .{
12973 .Rd = d.alias.encode(.{ .V = true }),
12974 .Rn = n.alias.encode(.{ .V = true }),
12975 .Q = arrangement.size(),
12976 },
12977 } } },
12978 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
12979 .fcvtas = .{
12980 .Rd = d.alias.encode(.{ .V = true }),
12981 .Rn = n.alias.encode(.{ .V = true }),
12982 .sz = arrangement.elemSz(),
12983 .Q = arrangement.size(),
12984 },
12985 } } },
12986 }
12987 },
12988 }
12989 }
12990 /// C7.2.72 FCVTAU (vector)
12991 /// C7.2.73 FCVTAU (scalar)
12992 pub fn fcvtau(d: Register, n: Register) Instruction {
12993 switch (d.format) {
12994 else => unreachable,
12995 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
12996 .fcvtau = .{
12997 .Rd = d.alias.encode(.{}),
12998 .Rn = n.alias.encode(.{ .V = true }),
12999 .ftype = .fromScalarSize(n.format.scalar),
13000 .sf = sf,
13001 },
13002 } } },
13003 .scalar => |elem_size| switch (n.format) {
13004 else => unreachable,
13005 .scalar => |ftype| {
13006 assert(ftype == elem_size);
13007 switch (elem_size) {
13008 else => unreachable,
13009 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
13010 .fcvtau = .{
13011 .Rd = d.alias.encode(.{ .V = true }),
13012 .Rn = n.alias.encode(.{ .V = true }),
13013 },
13014 } } },
13015 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
13016 .fcvtau = .{
13017 .Rd = d.alias.encode(.{ .V = true }),
13018 .Rn = n.alias.encode(.{ .V = true }),
13019 .sz = .fromScalarSize(elem_size),
13020 },
13021 } } },
13022 }
13023 },
13024 },
13025 .vector => |arrangement| {
13026 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13027 switch (arrangement.elemSize()) {
13028 else => unreachable,
13029 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13030 .fcvtau = .{
13031 .Rd = d.alias.encode(.{ .V = true }),
13032 .Rn = n.alias.encode(.{ .V = true }),
13033 .Q = arrangement.size(),
13034 },
13035 } } },
13036 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13037 .fcvtau = .{
13038 .Rd = d.alias.encode(.{ .V = true }),
13039 .Rn = n.alias.encode(.{ .V = true }),
13040 .sz = arrangement.elemSz(),
13041 .Q = arrangement.size(),
13042 },
13043 } } },
13044 }
13045 },
13046 }
13047 }
13048 /// C7.2.75 FCVTMS (vector)
13049 /// C7.2.76 FCVTMS (scalar)
13050 pub fn fcvtms(d: Register, n: Register) Instruction {
13051 switch (d.format) {
13052 else => unreachable,
13053 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
13054 .fcvtms = .{
13055 .Rd = d.alias.encode(.{}),
13056 .Rn = n.alias.encode(.{ .V = true }),
13057 .ftype = .fromScalarSize(n.format.scalar),
13058 .sf = sf,
13059 },
13060 } } },
13061 .scalar => |elem_size| switch (n.format) {
13062 else => unreachable,
13063 .scalar => |ftype| {
13064 assert(ftype == elem_size);
13065 switch (elem_size) {
13066 else => unreachable,
13067 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
13068 .fcvtms = .{
13069 .Rd = d.alias.encode(.{ .V = true }),
13070 .Rn = n.alias.encode(.{ .V = true }),
13071 },
13072 } } },
13073 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
13074 .fcvtms = .{
13075 .Rd = d.alias.encode(.{ .V = true }),
13076 .Rn = n.alias.encode(.{ .V = true }),
13077 .sz = .fromScalarSize(elem_size),
13078 },
13079 } } },
13080 }
13081 },
13082 },
13083 .vector => |arrangement| {
13084 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13085 switch (arrangement.elemSize()) {
13086 else => unreachable,
13087 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13088 .fcvtms = .{
13089 .Rd = d.alias.encode(.{ .V = true }),
13090 .Rn = n.alias.encode(.{ .V = true }),
13091 .Q = arrangement.size(),
13092 },
13093 } } },
13094 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13095 .fcvtms = .{
13096 .Rd = d.alias.encode(.{ .V = true }),
13097 .Rn = n.alias.encode(.{ .V = true }),
13098 .sz = arrangement.elemSz(),
13099 .Q = arrangement.size(),
13100 },
13101 } } },
13102 }
13103 },
13104 }
13105 }
13106 /// C7.2.77 FCVTMU (vector)
13107 /// C7.2.78 FCVTMU (scalar)
13108 pub fn fcvtmu(d: Register, n: Register) Instruction {
13109 switch (d.format) {
13110 else => unreachable,
13111 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
13112 .fcvtmu = .{
13113 .Rd = d.alias.encode(.{}),
13114 .Rn = n.alias.encode(.{ .V = true }),
13115 .ftype = .fromScalarSize(n.format.scalar),
13116 .sf = sf,
13117 },
13118 } } },
13119 .scalar => |elem_size| switch (n.format) {
13120 else => unreachable,
13121 .scalar => |ftype| {
13122 assert(ftype == elem_size);
13123 switch (elem_size) {
13124 else => unreachable,
13125 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
13126 .fcvtmu = .{
13127 .Rd = d.alias.encode(.{ .V = true }),
13128 .Rn = n.alias.encode(.{ .V = true }),
13129 },
13130 } } },
13131 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
13132 .fcvtmu = .{
13133 .Rd = d.alias.encode(.{ .V = true }),
13134 .Rn = n.alias.encode(.{ .V = true }),
13135 .sz = .fromScalarSize(elem_size),
13136 },
13137 } } },
13138 }
13139 },
13140 },
13141 .vector => |arrangement| {
13142 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13143 switch (arrangement.elemSize()) {
13144 else => unreachable,
13145 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13146 .fcvtmu = .{
13147 .Rd = d.alias.encode(.{ .V = true }),
13148 .Rn = n.alias.encode(.{ .V = true }),
13149 .Q = arrangement.size(),
13150 },
13151 } } },
13152 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13153 .fcvtmu = .{
13154 .Rd = d.alias.encode(.{ .V = true }),
13155 .Rn = n.alias.encode(.{ .V = true }),
13156 .sz = arrangement.elemSz(),
13157 .Q = arrangement.size(),
13158 },
13159 } } },
13160 }
13161 },
13162 }
13163 }
13164 /// C7.2.80 FCVTNS (vector)
13165 /// C7.2.81 FCVTNS (scalar)
13166 pub fn fcvtns(d: Register, n: Register) Instruction {
13167 switch (d.format) {
13168 else => unreachable,
13169 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
13170 .fcvtns = .{
13171 .Rd = d.alias.encode(.{}),
13172 .Rn = n.alias.encode(.{ .V = true }),
13173 .ftype = .fromScalarSize(n.format.scalar),
13174 .sf = sf,
13175 },
13176 } } },
13177 .scalar => |elem_size| switch (n.format) {
13178 else => unreachable,
13179 .scalar => |ftype| {
13180 assert(ftype == elem_size);
13181 switch (elem_size) {
13182 else => unreachable,
13183 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
13184 .fcvtns = .{
13185 .Rd = d.alias.encode(.{ .V = true }),
13186 .Rn = n.alias.encode(.{ .V = true }),
13187 },
13188 } } },
13189 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
13190 .fcvtns = .{
13191 .Rd = d.alias.encode(.{ .V = true }),
13192 .Rn = n.alias.encode(.{ .V = true }),
13193 .sz = .fromScalarSize(elem_size),
13194 },
13195 } } },
13196 }
13197 },
13198 },
13199 .vector => |arrangement| {
13200 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13201 switch (arrangement.elemSize()) {
13202 else => unreachable,
13203 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13204 .fcvtns = .{
13205 .Rd = d.alias.encode(.{ .V = true }),
13206 .Rn = n.alias.encode(.{ .V = true }),
13207 .Q = arrangement.size(),
13208 },
13209 } } },
13210 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13211 .fcvtns = .{
13212 .Rd = d.alias.encode(.{ .V = true }),
13213 .Rn = n.alias.encode(.{ .V = true }),
13214 .sz = arrangement.elemSz(),
13215 .Q = arrangement.size(),
13216 },
13217 } } },
13218 }
13219 },
13220 }
13221 }
13222 /// C7.2.82 FCVTNU (vector)
13223 /// C7.2.83 FCVTNU (scalar)
13224 pub fn fcvtnu(d: Register, n: Register) Instruction {
13225 switch (d.format) {
13226 else => unreachable,
13227 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
13228 .fcvtnu = .{
13229 .Rd = d.alias.encode(.{}),
13230 .Rn = n.alias.encode(.{ .V = true }),
13231 .ftype = .fromScalarSize(n.format.scalar),
13232 .sf = sf,
13233 },
13234 } } },
13235 .scalar => |elem_size| switch (n.format) {
13236 else => unreachable,
13237 .scalar => |ftype| {
13238 assert(ftype == elem_size);
13239 switch (elem_size) {
13240 else => unreachable,
13241 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
13242 .fcvtnu = .{
13243 .Rd = d.alias.encode(.{ .V = true }),
13244 .Rn = n.alias.encode(.{ .V = true }),
13245 },
13246 } } },
13247 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
13248 .fcvtnu = .{
13249 .Rd = d.alias.encode(.{ .V = true }),
13250 .Rn = n.alias.encode(.{ .V = true }),
13251 .sz = .fromScalarSize(elem_size),
13252 },
13253 } } },
13254 }
13255 },
13256 },
13257 .vector => |arrangement| {
13258 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13259 switch (arrangement.elemSize()) {
13260 else => unreachable,
13261 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13262 .fcvtnu = .{
13263 .Rd = d.alias.encode(.{ .V = true }),
13264 .Rn = n.alias.encode(.{ .V = true }),
13265 .Q = arrangement.size(),
13266 },
13267 } } },
13268 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13269 .fcvtnu = .{
13270 .Rd = d.alias.encode(.{ .V = true }),
13271 .Rn = n.alias.encode(.{ .V = true }),
13272 .sz = arrangement.elemSz(),
13273 .Q = arrangement.size(),
13274 },
13275 } } },
13276 }
13277 },
13278 }
13279 }
13280 /// C7.2.84 FCVTPS (vector)
13281 /// C7.2.85 FCVTPS (scalar)
13282 pub fn fcvtps(d: Register, n: Register) Instruction {
13283 switch (d.format) {
13284 else => unreachable,
13285 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
13286 .fcvtps = .{
13287 .Rd = d.alias.encode(.{}),
13288 .Rn = n.alias.encode(.{ .V = true }),
13289 .ftype = .fromScalarSize(n.format.scalar),
13290 .sf = sf,
13291 },
13292 } } },
13293 .scalar => |elem_size| switch (n.format) {
13294 else => unreachable,
13295 .scalar => |ftype| {
13296 assert(ftype == elem_size);
13297 switch (elem_size) {
13298 else => unreachable,
13299 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
13300 .fcvtps = .{
13301 .Rd = d.alias.encode(.{ .V = true }),
13302 .Rn = n.alias.encode(.{ .V = true }),
13303 },
13304 } } },
13305 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
13306 .fcvtps = .{
13307 .Rd = d.alias.encode(.{ .V = true }),
13308 .Rn = n.alias.encode(.{ .V = true }),
13309 .sz = .fromScalarSize(elem_size),
13310 },
13311 } } },
13312 }
13313 },
13314 },
13315 .vector => |arrangement| {
13316 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13317 switch (arrangement.elemSize()) {
13318 else => unreachable,
13319 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13320 .fcvtps = .{
13321 .Rd = d.alias.encode(.{ .V = true }),
13322 .Rn = n.alias.encode(.{ .V = true }),
13323 .Q = arrangement.size(),
13324 },
13325 } } },
13326 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13327 .fcvtps = .{
13328 .Rd = d.alias.encode(.{ .V = true }),
13329 .Rn = n.alias.encode(.{ .V = true }),
13330 .sz = arrangement.elemSz(),
13331 .Q = arrangement.size(),
13332 },
13333 } } },
13334 }
13335 },
13336 }
13337 }
13338 /// C7.2.86 FCVTPU (vector)
13339 /// C7.2.87 FCVTPU (scalar)
13340 pub fn fcvtpu(d: Register, n: Register) Instruction {
13341 switch (d.format) {
13342 else => unreachable,
13343 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
13344 .fcvtpu = .{
13345 .Rd = d.alias.encode(.{}),
13346 .Rn = n.alias.encode(.{ .V = true }),
13347 .ftype = .fromScalarSize(n.format.scalar),
13348 .sf = sf,
13349 },
13350 } } },
13351 .scalar => |elem_size| switch (n.format) {
13352 else => unreachable,
13353 .scalar => |ftype| {
13354 assert(ftype == elem_size);
13355 switch (elem_size) {
13356 else => unreachable,
13357 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
13358 .fcvtpu = .{
13359 .Rd = d.alias.encode(.{ .V = true }),
13360 .Rn = n.alias.encode(.{ .V = true }),
13361 },
13362 } } },
13363 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
13364 .fcvtpu = .{
13365 .Rd = d.alias.encode(.{ .V = true }),
13366 .Rn = n.alias.encode(.{ .V = true }),
13367 .sz = .fromScalarSize(elem_size),
13368 },
13369 } } },
13370 }
13371 },
13372 },
13373 .vector => |arrangement| {
13374 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13375 switch (arrangement.elemSize()) {
13376 else => unreachable,
13377 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13378 .fcvtpu = .{
13379 .Rd = d.alias.encode(.{ .V = true }),
13380 .Rn = n.alias.encode(.{ .V = true }),
13381 .Q = arrangement.size(),
13382 },
13383 } } },
13384 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13385 .fcvtpu = .{
13386 .Rd = d.alias.encode(.{ .V = true }),
13387 .Rn = n.alias.encode(.{ .V = true }),
13388 .sz = arrangement.elemSz(),
13389 .Q = arrangement.size(),
13390 },
13391 } } },
13392 }
13393 },
13394 }
13395 }
13396 /// C7.2.90 FCVTZS (vector, integer)
13397 /// C7.2.92 FCVTZS (scalar, integer)
13398 pub fn fcvtzs(d: Register, n: Register) Instruction {
13399 switch (d.format) {
13400 else => unreachable,
13401 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
13402 .fcvtzs = .{
13403 .Rd = d.alias.encode(.{}),
13404 .Rn = n.alias.encode(.{ .V = true }),
13405 .ftype = .fromScalarSize(n.format.scalar),
13406 .sf = sf,
13407 },
13408 } } },
13409 .scalar => |elem_size| switch (n.format) {
13410 else => unreachable,
13411 .scalar => |ftype| {
13412 assert(ftype == elem_size);
13413 switch (elem_size) {
13414 else => unreachable,
13415 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
13416 .fcvtzs = .{
13417 .Rd = d.alias.encode(.{ .V = true }),
13418 .Rn = n.alias.encode(.{ .V = true }),
13419 },
13420 } } },
13421 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
13422 .fcvtzs = .{
13423 .Rd = d.alias.encode(.{ .V = true }),
13424 .Rn = n.alias.encode(.{ .V = true }),
13425 .sz = .fromScalarSize(elem_size),
13426 },
13427 } } },
13428 }
13429 },
13430 },
13431 .vector => |arrangement| {
13432 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13433 switch (arrangement.elemSize()) {
13434 else => unreachable,
13435 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13436 .fcvtzs = .{
13437 .Rd = d.alias.encode(.{ .V = true }),
13438 .Rn = n.alias.encode(.{ .V = true }),
13439 .Q = arrangement.size(),
13440 },
13441 } } },
13442 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13443 .fcvtzs = .{
13444 .Rd = d.alias.encode(.{ .V = true }),
13445 .Rn = n.alias.encode(.{ .V = true }),
13446 .sz = arrangement.elemSz(),
13447 .Q = arrangement.size(),
13448 },
13449 } } },
13450 }
13451 },
13452 }
13453 }
13454 /// C7.2.94 FCVTZU (vector, integer)
13455 /// C7.2.96 FCVTZU (scalar, integer)
13456 pub fn fcvtzu(d: Register, n: Register) Instruction {
13457 switch (d.format) {
13458 else => unreachable,
13459 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
13460 .fcvtzu = .{
13461 .Rd = d.alias.encode(.{}),
13462 .Rn = n.alias.encode(.{ .V = true }),
13463 .ftype = .fromScalarSize(n.format.scalar),
13464 .sf = sf,
13465 },
13466 } } },
13467 .scalar => |elem_size| switch (n.format) {
13468 else => unreachable,
13469 .scalar => |ftype| {
13470 assert(ftype == elem_size);
13471 switch (elem_size) {
13472 else => unreachable,
13473 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
13474 .fcvtzu = .{
13475 .Rd = d.alias.encode(.{ .V = true }),
13476 .Rn = n.alias.encode(.{ .V = true }),
13477 },
13478 } } },
13479 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
13480 .fcvtzu = .{
13481 .Rd = d.alias.encode(.{ .V = true }),
13482 .Rn = n.alias.encode(.{ .V = true }),
13483 .sz = .fromScalarSize(elem_size),
13484 },
13485 } } },
13486 }
13487 },
13488 },
13489 .vector => |arrangement| {
13490 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13491 switch (arrangement.elemSize()) {
13492 else => unreachable,
13493 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13494 .fcvtzu = .{
13495 .Rd = d.alias.encode(.{ .V = true }),
13496 .Rn = n.alias.encode(.{ .V = true }),
13497 .Q = arrangement.size(),
13498 },
13499 } } },
13500 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13501 .fcvtzu = .{
13502 .Rd = d.alias.encode(.{ .V = true }),
13503 .Rn = n.alias.encode(.{ .V = true }),
13504 .sz = arrangement.elemSz(),
13505 .Q = arrangement.size(),
13506 },
13507 } } },
13508 }
13509 },
13510 }
13511 }
13512 /// C7.2.98 FDIV (scalar)
13513 pub fn fdiv(d: Register, n: Register, m: Register) Instruction {
13514 const ftype = d.format.scalar;
13515 assert(n.format.scalar == ftype and m.format.scalar == ftype);
13516 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
13517 .fdiv = .{
13518 .Rd = d.alias.encode(.{ .V = true }),
13519 .Rn = n.alias.encode(.{ .V = true }),
13520 .Rm = m.alias.encode(.{ .V = true }),
13521 .ftype = .fromScalarSize(ftype),
13522 },
13523 } } };
13524 }
13525 /// C7.2.99 FJCVTZS
13526 pub fn fjcvtzs(d: Register, n: Register) Instruction {
13527 assert(d.format.general == .word);
13528 assert(n.format.scalar == .double);
13529 return .{ .data_processing_vector = .{ .convert_float_integer = .{
13530 .fjcvtzs = .{
13531 .Rd = d.alias.encode(.{}),
13532 .Rn = n.alias.encode(.{ .V = true }),
13533 },
13534 } } };
13535 }
13536 /// C7.2.100 FMADD
13537 pub fn fmadd(d: Register, n: Register, m: Register, a: Register) Instruction {
13538 const ftype = d.format.scalar;
13539 assert(n.format.scalar == ftype and m.format.scalar == ftype and a.format.scalar == ftype);
13540 return .{ .data_processing_vector = .{ .float_data_processing_three_source = .{
13541 .fmadd = .{
13542 .Rd = d.alias.encode(.{ .V = true }),
13543 .Rn = n.alias.encode(.{ .V = true }),
13544 .Rm = m.alias.encode(.{ .V = true }),
13545 .Ra = a.alias.encode(.{ .V = true }),
13546 .ftype = .fromScalarSize(ftype),
13547 },
13548 } } };
13549 }
13550 /// C7.2.102 FMAX (scalar)
13551 pub fn fmax(d: Register, n: Register, m: Register) Instruction {
13552 const ftype = d.format.scalar;
13553 assert(n.format.scalar == ftype and m.format.scalar == ftype);
13554 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
13555 .fmax = .{
13556 .Rd = d.alias.encode(.{ .V = true }),
13557 .Rn = n.alias.encode(.{ .V = true }),
13558 .Rm = m.alias.encode(.{ .V = true }),
13559 .ftype = .fromScalarSize(ftype),
13560 },
13561 } } };
13562 }
13563 /// C7.2.104 FMAXNM (scalar)
13564 pub fn fmaxnm(d: Register, n: Register, m: Register) Instruction {
13565 const ftype = d.format.scalar;
13566 assert(n.format.scalar == ftype and m.format.scalar == ftype);
13567 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
13568 .fmaxnm = .{
13569 .Rd = d.alias.encode(.{ .V = true }),
13570 .Rn = n.alias.encode(.{ .V = true }),
13571 .Rm = m.alias.encode(.{ .V = true }),
13572 .ftype = .fromScalarSize(ftype),
13573 },
13574 } } };
13575 }
13576 /// C7.2.112 FMIN (scalar)
13577 pub fn fmin(d: Register, n: Register, m: Register) Instruction {
13578 const ftype = d.format.scalar;
13579 assert(n.format.scalar == ftype and m.format.scalar == ftype);
13580 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
13581 .fmin = .{
13582 .Rd = d.alias.encode(.{ .V = true }),
13583 .Rn = n.alias.encode(.{ .V = true }),
13584 .Rm = m.alias.encode(.{ .V = true }),
13585 .ftype = .fromScalarSize(ftype),
13586 },
13587 } } };
13588 }
13589 /// C7.2.114 FMINNM (scalar)
13590 pub fn fminnm(d: Register, n: Register, m: Register) Instruction {
13591 const ftype = d.format.scalar;
13592 assert(n.format.scalar == ftype and m.format.scalar == ftype);
13593 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
13594 .fminnm = .{
13595 .Rd = d.alias.encode(.{ .V = true }),
13596 .Rn = n.alias.encode(.{ .V = true }),
13597 .Rm = m.alias.encode(.{ .V = true }),
13598 .ftype = .fromScalarSize(ftype),
13599 },
13600 } } };
13601 }
13602 /// C7.2.129 FMOV (vector, immediate)
13603 /// C7.2.130 FMOV (register)
13604 /// C7.2.131 FMOV (general)
13605 /// C7.2.132 FMOV (scalar, immediate)
13606 pub fn fmov(d: Register, form: union(enum) { immediate: f16, register: Register }) Instruction {
13607 switch (form) {
13608 .immediate => |immediate| {
13609 const repr: std.math.FloatRepr(f16) = @bitCast(immediate);
13610 const imm: DataProcessingVector.FloatImmediate.Fmov.Imm8 = .{
13611 .mantissa = @intCast(@shrExact(repr.mantissa, 6)),
13612 .exponent = @intCast(repr.exponent.unbias() - 1),
13613 .sign = repr.sign,
13614 };
13615 switch (d.format) {
13616 else => unreachable,
13617 .scalar => |ftype| return .{ .data_processing_vector = .{ .float_immediate = .{
13618 .fmov = .{
13619 .Rd = d.alias.encode(.{ .V = true }),
13620 .imm8 = imm,
13621 .ftype = .fromScalarSize(ftype),
13622 },
13623 } } },
13624 .vector => |arrangement| {
13625 const elem_size = arrangement.elemSize();
13626 assert(arrangement.len() > 1);
13627 const mod_imm = imm.toModified();
13628 return .{ .data_processing_vector = .{ .simd_modified_immediate = .{
13629 .fmov = .{
13630 .Rd = d.alias.encode(.{ .V = true }),
13631 .imm5 = mod_imm.imm5,
13632 .o2 = switch (elem_size) {
13633 .byte => unreachable,
13634 .half => 0b1,
13635 .single, .double => 0b0,
13636 },
13637 .imm3 = mod_imm.imm3,
13638 .op = switch (elem_size) {
13639 .byte => unreachable,
13640 .half, .single => 0b0,
13641 .double => 0b1,
13642 },
13643 .Q = arrangement.size(),
13644 },
13645 } } };
13646 },
13647 }
13648 },
13649 .register => |n| switch (d.format) {
13650 else => unreachable,
13651 .general => |sf| switch (n.format) {
13652 else => unreachable,
13653 .scalar => |ftype| {
13654 switch (ftype) {
13655 else => unreachable,
13656 .half => {},
13657 .single => assert(sf == .word),
13658 .double => assert(sf == .doubleword),
13659 }
13660 return .{ .data_processing_vector = .{ .convert_float_integer = .{
13661 .fmov = .{
13662 .Rd = d.alias.encode(.{}),
13663 .Rn = n.alias.encode(.{ .V = true }),
13664 .opcode = .float_to_integer,
13665 .rmode = .@"0",
13666 .ftype = .fromScalarSize(ftype),
13667 .sf = sf,
13668 },
13669 } } };
13670 },
13671 .element => |element| return .{ .data_processing_vector = .{ .convert_float_integer = .{
13672 .fmov = .{
13673 .Rd = d.alias.encode(.{}),
13674 .Rn = n.alias.encode(.{ .V = true }),
13675 .opcode = .float_to_integer,
13676 .rmode = switch (element.index) {
13677 else => unreachable,
13678 1 => .@"1",
13679 },
13680 .ftype = switch (element.size) {
13681 else => unreachable,
13682 .double => .quad,
13683 },
13684 .sf = sf,
13685 },
13686 } } },
13687 },
13688 .scalar => |ftype| switch (n.format) {
13689 else => unreachable,
13690 .general => |sf| {
13691 switch (ftype) {
13692 else => unreachable,
13693 .half => {},
13694 .single => assert(sf == .word),
13695 .double => assert(sf == .doubleword),
13696 }
13697 return .{ .data_processing_vector = .{ .convert_float_integer = .{
13698 .fmov = .{
13699 .Rd = d.alias.encode(.{ .V = true }),
13700 .Rn = n.alias.encode(.{}),
13701 .opcode = .integer_to_float,
13702 .rmode = .@"0",
13703 .ftype = .fromScalarSize(ftype),
13704 .sf = sf,
13705 },
13706 } } };
13707 },
13708 .scalar => {
13709 assert(n.format.scalar == ftype);
13710 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
13711 .fmov = .{
13712 .Rd = d.alias.encode(.{ .V = true }),
13713 .Rn = n.alias.encode(.{ .V = true }),
13714 .ftype = .fromScalarSize(ftype),
13715 },
13716 } } };
13717 },
13718 },
13719 .element => |element| switch (n.format) {
13720 else => unreachable,
13721 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
13722 .fmov = .{
13723 .Rd = d.alias.encode(.{ .V = true }),
13724 .Rn = n.alias.encode(.{}),
13725 .opcode = .integer_to_float,
13726 .rmode = switch (element.index) {
13727 else => unreachable,
13728 1 => .@"1",
13729 },
13730 .ftype = switch (element.size) {
13731 else => unreachable,
13732 .double => .quad,
13733 },
13734 .sf = sf,
13735 },
13736 } } },
13737 },
13738 },
13739 }
13740 }
13741 /// C7.2.133 FMSUB
13742 pub fn fmsub(d: Register, n: Register, m: Register, a: Register) Instruction {
13743 const ftype = d.format.scalar;
13744 assert(n.format.scalar == ftype and m.format.scalar == ftype and a.format.scalar == ftype);
13745 return .{ .data_processing_vector = .{ .float_data_processing_three_source = .{
13746 .fmsub = .{
13747 .Rd = d.alias.encode(.{ .V = true }),
13748 .Rn = n.alias.encode(.{ .V = true }),
13749 .Rm = m.alias.encode(.{ .V = true }),
13750 .Ra = a.alias.encode(.{ .V = true }),
13751 .ftype = .fromScalarSize(ftype),
13752 },
13753 } } };
13754 }
13755 /// C7.2.136 FMUL (scalar)
13756 pub fn fmul(d: Register, n: Register, m: Register) Instruction {
13757 const ftype = d.format.scalar;
13758 assert(n.format.scalar == ftype and m.format.scalar == ftype);
13759 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
13760 .fmul = .{
13761 .Rd = d.alias.encode(.{ .V = true }),
13762 .Rn = n.alias.encode(.{ .V = true }),
13763 .Rm = m.alias.encode(.{ .V = true }),
13764 .ftype = .fromScalarSize(ftype),
13765 },
13766 } } };
13767 }
13768 /// C7.2.139 FNEG (vector)
13769 /// C7.2.140 FNEG (scalar)
13770 pub fn fneg(d: Register, n: Register) Instruction {
13771 switch (d.format) {
13772 else => unreachable,
13773 .vector => |arrangement| {
13774 assert(n.format.vector == arrangement);
13775 switch (arrangement.elemSize()) {
13776 else => unreachable,
13777 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13778 .fneg = .{
13779 .Rd = d.alias.encode(.{ .V = true }),
13780 .Rn = n.alias.encode(.{ .V = true }),
13781 .Q = arrangement.size(),
13782 },
13783 } } },
13784 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13785 .fneg = .{
13786 .Rd = d.alias.encode(.{ .V = true }),
13787 .Rn = n.alias.encode(.{ .V = true }),
13788 .sz = arrangement.elemSz(),
13789 .Q = arrangement.size(),
13790 },
13791 } } },
13792 }
13793 },
13794 .scalar => |ftype| {
13795 assert(n.format.scalar == ftype);
13796 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
13797 .fneg = .{
13798 .Rd = d.alias.encode(.{ .V = true }),
13799 .Rn = n.alias.encode(.{ .V = true }),
13800 .ftype = .fromScalarSize(ftype),
13801 },
13802 } } };
13803 },
13804 }
13805 }
13806 /// C7.2.141 FNMADD
13807 pub fn fnmadd(d: Register, n: Register, m: Register, a: Register) Instruction {
13808 const ftype = d.format.scalar;
13809 assert(n.format.scalar == ftype and m.format.scalar == ftype and a.format.scalar == ftype);
13810 return .{ .data_processing_vector = .{ .float_data_processing_three_source = .{
13811 .fnmadd = .{
13812 .Rd = d.alias.encode(.{ .V = true }),
13813 .Rn = n.alias.encode(.{ .V = true }),
13814 .Rm = m.alias.encode(.{ .V = true }),
13815 .Ra = a.alias.encode(.{ .V = true }),
13816 .ftype = .fromScalarSize(ftype),
13817 },
13818 } } };
13819 }
13820 /// C7.2.142 FNMSUB
13821 pub fn fnmsub(d: Register, n: Register, m: Register, a: Register) Instruction {
13822 const ftype = d.format.scalar;
13823 assert(n.format.scalar == ftype and m.format.scalar == ftype and a.format.scalar == ftype);
13824 return .{ .data_processing_vector = .{ .float_data_processing_three_source = .{
13825 .fnmsub = .{
13826 .Rd = d.alias.encode(.{ .V = true }),
13827 .Rn = n.alias.encode(.{ .V = true }),
13828 .Rm = m.alias.encode(.{ .V = true }),
13829 .Ra = a.alias.encode(.{ .V = true }),
13830 .ftype = .fromScalarSize(ftype),
13831 },
13832 } } };
13833 }
13834 /// C7.2.143 FNMUL (scalar)
13835 pub fn fnmul(d: Register, n: Register, m: Register) Instruction {
13836 const ftype = d.format.scalar;
13837 assert(n.format.scalar == ftype and m.format.scalar == ftype);
13838 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
13839 .fnmul = .{
13840 .Rd = d.alias.encode(.{ .V = true }),
13841 .Rn = n.alias.encode(.{ .V = true }),
13842 .Rm = m.alias.encode(.{ .V = true }),
13843 .ftype = .fromScalarSize(ftype),
13844 },
13845 } } };
13846 }
13847 /// C7.2.155 FRINTA (vector)
13848 /// C7.2.156 FRINTA (scalar)
13849 pub fn frinta(d: Register, n: Register) Instruction {
13850 switch (d.format) {
13851 else => unreachable,
13852 .vector => |arrangement| {
13853 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13854 switch (arrangement.elemSize()) {
13855 else => unreachable,
13856 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13857 .frinta = .{
13858 .Rd = d.alias.encode(.{ .V = true }),
13859 .Rn = n.alias.encode(.{ .V = true }),
13860 .Q = arrangement.size(),
13861 },
13862 } } },
13863 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13864 .frinta = .{
13865 .Rd = d.alias.encode(.{ .V = true }),
13866 .Rn = n.alias.encode(.{ .V = true }),
13867 .sz = arrangement.elemSz(),
13868 .Q = arrangement.size(),
13869 },
13870 } } },
13871 }
13872 },
13873 .scalar => |ftype| {
13874 assert(n.format.scalar == ftype);
13875 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
13876 .frinta = .{
13877 .Rd = d.alias.encode(.{ .V = true }),
13878 .Rn = n.alias.encode(.{ .V = true }),
13879 .ftype = .fromScalarSize(ftype),
13880 },
13881 } } };
13882 },
13883 }
13884 }
13885 /// C7.2.157 FRINTI (vector)
13886 /// C7.2.158 FRINTI (scalar)
13887 pub fn frinti(d: Register, n: Register) Instruction {
13888 switch (d.format) {
13889 else => unreachable,
13890 .vector => |arrangement| {
13891 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13892 switch (arrangement.elemSize()) {
13893 else => unreachable,
13894 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13895 .frinti = .{
13896 .Rd = d.alias.encode(.{ .V = true }),
13897 .Rn = n.alias.encode(.{ .V = true }),
13898 .Q = arrangement.size(),
13899 },
13900 } } },
13901 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13902 .frinti = .{
13903 .Rd = d.alias.encode(.{ .V = true }),
13904 .Rn = n.alias.encode(.{ .V = true }),
13905 .sz = arrangement.elemSz(),
13906 .Q = arrangement.size(),
13907 },
13908 } } },
13909 }
13910 },
13911 .scalar => |ftype| {
13912 assert(n.format.scalar == ftype);
13913 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
13914 .frinti = .{
13915 .Rd = d.alias.encode(.{ .V = true }),
13916 .Rn = n.alias.encode(.{ .V = true }),
13917 .ftype = .fromScalarSize(ftype),
13918 },
13919 } } };
13920 },
13921 }
13922 }
13923 /// C7.2.159 FRINTM (vector)
13924 /// C7.2.160 FRINTM (scalar)
13925 pub fn frintm(d: Register, n: Register) Instruction {
13926 switch (d.format) {
13927 else => unreachable,
13928 .vector => |arrangement| {
13929 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13930 switch (arrangement.elemSize()) {
13931 else => unreachable,
13932 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13933 .frintm = .{
13934 .Rd = d.alias.encode(.{ .V = true }),
13935 .Rn = n.alias.encode(.{ .V = true }),
13936 .Q = arrangement.size(),
13937 },
13938 } } },
13939 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13940 .frintm = .{
13941 .Rd = d.alias.encode(.{ .V = true }),
13942 .Rn = n.alias.encode(.{ .V = true }),
13943 .sz = arrangement.elemSz(),
13944 .Q = arrangement.size(),
13945 },
13946 } } },
13947 }
13948 },
13949 .scalar => |ftype| {
13950 assert(n.format.scalar == ftype);
13951 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
13952 .frintm = .{
13953 .Rd = d.alias.encode(.{ .V = true }),
13954 .Rn = n.alias.encode(.{ .V = true }),
13955 .ftype = .fromScalarSize(ftype),
13956 },
13957 } } };
13958 },
13959 }
13960 }
13961 /// C7.2.161 FRINTN (vector)
13962 /// C7.2.162 FRINTN (scalar)
13963 pub fn frintn(d: Register, n: Register) Instruction {
13964 switch (d.format) {
13965 else => unreachable,
13966 .vector => |arrangement| {
13967 assert(arrangement != .@"1d" and n.format.vector == arrangement);
13968 switch (arrangement.elemSize()) {
13969 else => unreachable,
13970 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
13971 .frintn = .{
13972 .Rd = d.alias.encode(.{ .V = true }),
13973 .Rn = n.alias.encode(.{ .V = true }),
13974 .Q = arrangement.size(),
13975 },
13976 } } },
13977 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
13978 .frintn = .{
13979 .Rd = d.alias.encode(.{ .V = true }),
13980 .Rn = n.alias.encode(.{ .V = true }),
13981 .sz = arrangement.elemSz(),
13982 .Q = arrangement.size(),
13983 },
13984 } } },
13985 }
13986 },
13987 .scalar => |ftype| {
13988 assert(n.format.scalar == ftype);
13989 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
13990 .frintn = .{
13991 .Rd = d.alias.encode(.{ .V = true }),
13992 .Rn = n.alias.encode(.{ .V = true }),
13993 .ftype = .fromScalarSize(ftype),
13994 },
13995 } } };
13996 },
13997 }
13998 }
13999 /// C7.2.163 FRINTP (vector)
14000 /// C7.2.164 FRINTP (scalar)
14001 pub fn frintp(d: Register, n: Register) Instruction {
14002 switch (d.format) {
14003 else => unreachable,
14004 .vector => |arrangement| {
14005 assert(arrangement != .@"1d" and n.format.vector == arrangement);
14006 switch (arrangement.elemSize()) {
14007 else => unreachable,
14008 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
14009 .frintp = .{
14010 .Rd = d.alias.encode(.{ .V = true }),
14011 .Rn = n.alias.encode(.{ .V = true }),
14012 .Q = arrangement.size(),
14013 },
14014 } } },
14015 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
14016 .frintp = .{
14017 .Rd = d.alias.encode(.{ .V = true }),
14018 .Rn = n.alias.encode(.{ .V = true }),
14019 .sz = arrangement.elemSz(),
14020 .Q = arrangement.size(),
14021 },
14022 } } },
14023 }
14024 },
14025 .scalar => |ftype| {
14026 assert(n.format.scalar == ftype);
14027 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
14028 .frintp = .{
14029 .Rd = d.alias.encode(.{ .V = true }),
14030 .Rn = n.alias.encode(.{ .V = true }),
14031 .ftype = .fromScalarSize(ftype),
14032 },
14033 } } };
14034 },
14035 }
14036 }
14037 /// C7.2.165 FRINTX (vector)
14038 /// C7.2.166 FRINTX (scalar)
14039 pub fn frintx(d: Register, n: Register) Instruction {
14040 switch (d.format) {
14041 else => unreachable,
14042 .vector => |arrangement| {
14043 assert(arrangement != .@"1d" and n.format.vector == arrangement);
14044 switch (arrangement.elemSize()) {
14045 else => unreachable,
14046 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
14047 .frintx = .{
14048 .Rd = d.alias.encode(.{ .V = true }),
14049 .Rn = n.alias.encode(.{ .V = true }),
14050 .Q = arrangement.size(),
14051 },
14052 } } },
14053 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
14054 .frintx = .{
14055 .Rd = d.alias.encode(.{ .V = true }),
14056 .Rn = n.alias.encode(.{ .V = true }),
14057 .sz = arrangement.elemSz(),
14058 .Q = arrangement.size(),
14059 },
14060 } } },
14061 }
14062 },
14063 .scalar => |ftype| {
14064 assert(n.format.scalar == ftype);
14065 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
14066 .frintx = .{
14067 .Rd = d.alias.encode(.{ .V = true }),
14068 .Rn = n.alias.encode(.{ .V = true }),
14069 .ftype = .fromScalarSize(ftype),
14070 },
14071 } } };
14072 },
14073 }
14074 }
14075 /// C7.2.167 FRINTZ (vector)
14076 /// C7.2.168 FRINTZ (scalar)
14077 pub fn frintz(d: Register, n: Register) Instruction {
14078 switch (d.format) {
14079 else => unreachable,
14080 .vector => |arrangement| {
14081 assert(arrangement != .@"1d" and n.format.vector == arrangement);
14082 switch (arrangement.elemSize()) {
14083 else => unreachable,
14084 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
14085 .frintz = .{
14086 .Rd = d.alias.encode(.{ .V = true }),
14087 .Rn = n.alias.encode(.{ .V = true }),
14088 .Q = arrangement.size(),
14089 },
14090 } } },
14091 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
14092 .frintz = .{
14093 .Rd = d.alias.encode(.{ .V = true }),
14094 .Rn = n.alias.encode(.{ .V = true }),
14095 .sz = arrangement.elemSz(),
14096 .Q = arrangement.size(),
14097 },
14098 } } },
14099 }
14100 },
14101 .scalar => |ftype| {
14102 assert(n.format.scalar == ftype);
14103 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
14104 .frintz = .{
14105 .Rd = d.alias.encode(.{ .V = true }),
14106 .Rn = n.alias.encode(.{ .V = true }),
14107 .ftype = .fromScalarSize(ftype),
14108 },
14109 } } };
14110 },
14111 }
14112 }
14113 /// C7.2.171 FSQRT (vector)
14114 /// C7.2.172 FSQRT (scalar)
14115 pub fn fsqrt(d: Register, n: Register) Instruction {
14116 switch (d.format) {
14117 else => unreachable,
14118 .vector => |arrangement| {
14119 assert(n.format.vector == arrangement);
14120 switch (arrangement.elemSize()) {
14121 else => unreachable,
14122 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
14123 .fsqrt = .{
14124 .Rd = d.alias.encode(.{ .V = true }),
14125 .Rn = n.alias.encode(.{ .V = true }),
14126 .Q = arrangement.size(),
14127 },
14128 } } },
14129 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
14130 .fsqrt = .{
14131 .Rd = d.alias.encode(.{ .V = true }),
14132 .Rn = n.alias.encode(.{ .V = true }),
14133 .sz = arrangement.elemSz(),
14134 .Q = arrangement.size(),
14135 },
14136 } } },
14137 }
14138 },
14139 .scalar => |ftype| {
14140 assert(n.format.scalar == ftype);
14141 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
14142 .fsqrt = .{
14143 .Rd = d.alias.encode(.{ .V = true }),
14144 .Rn = n.alias.encode(.{ .V = true }),
14145 .ftype = .fromScalarSize(ftype),
14146 },
14147 } } };
14148 },
14149 }
14150 }
14151 /// C7.2.174 FSUB (scalar)
14152 pub fn fsub(d: Register, n: Register, m: Register) Instruction {
14153 const ftype = d.format.scalar;
14154 assert(n.format.scalar == ftype and m.format.scalar == ftype);
14155 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
14156 .fsub = .{
14157 .Rd = d.alias.encode(.{ .V = true }),
14158 .Rn = n.alias.encode(.{ .V = true }),
14159 .Rm = m.alias.encode(.{ .V = true }),
14160 .ftype = .fromScalarSize(ftype),
14161 },
14162 } } };
14163 }
14164 /// C6.2.126 HINT
14165 pub fn hint(imm: u7) Instruction {
14166 return .{ .branch_exception_generating_system = .{ .hints = .{
14167 .group = .{
14168 .op2 = @truncate(imm >> 0),
14169 .CRm = @intCast(imm >> 3),
14170 },
14171 } } };
14172 }
14173 /// C6.2.127 HLT
14174 pub fn hlt(imm: u16) Instruction {
14175 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
14176 .hlt = .{ .imm16 = imm },
14177 } } };
14178 }
14179 /// C6.2.128 HVC
14180 pub fn hvc(imm: u16) Instruction {
14181 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
14182 .hvc = .{ .imm16 = imm },
14183 } } };
14184 }
14185 /// C7.2.175 INS (element)
14186 /// C7.2.176 INS (general)
14187 pub fn ins(d: Register, n: Register) Instruction {
14188 const elem_size = d.format.element.size;
14189 switch (n.format) {
14190 else => unreachable,
14191 .element => |element| {
14192 assert(elem_size == element.size);
14193 return .{ .data_processing_vector = .{ .simd_copy = .{
14194 .ins = .{
14195 .Rd = d.alias.encode(.{ .V = true }),
14196 .Rn = n.alias.encode(.{ .V = true }),
14197 .imm4 = .{ .element = element.index << @intCast(@intFromEnum(elem_size)) },
14198 .imm5 = (@as(u5, d.format.element.index) << 1 | @as(u5, 0b1) << 0) << @intFromEnum(elem_size),
14199 .op = .element,
14200 },
14201 } } };
14202 },
14203 .general => |general| {
14204 assert(general == @as(Register.GeneralSize, switch (elem_size) {
14205 else => unreachable,
14206 .byte, .half, .single => .word,
14207 .double => .doubleword,
14208 }));
14209 return .{ .data_processing_vector = .{ .simd_copy = .{
14210 .ins = .{
14211 .Rd = d.alias.encode(.{ .V = true }),
14212 .Rn = n.alias.encode(.{}),
14213 .imm4 = .{ .general = .general },
14214 .imm5 = (@as(u5, d.format.element.index) << 1 | @as(u5, 0b1) << 0) << @intFromEnum(elem_size),
14215 .op = .general,
14216 },
14217 } } };
14218 },
14219 }
14220 }
14221 /// C6.2.131 ISB
14222 pub fn isb(option: BranchExceptionGeneratingSystem.Barriers.Option) Instruction {
14223 return .{ .branch_exception_generating_system = .{ .barriers = .{
14224 .isb = .{
14225 .CRm = option,
14226 },
14227 } } };
14228 }
14229 /// C6.2.164 LDP
14230 /// C7.2.190 LDP (SIMD&FP)
14231 pub fn ldp(t1: Register, t2: Register, form: union(enum) {
14232 post_index: struct { base: Register, index: i10 },
14233 pre_index: struct { base: Register, index: i10 },
14234 signed_offset: struct { base: Register, offset: i10 = 0 },
14235 base: Register,
14236 }) Instruction {
14237 switch (t1.format) {
14238 else => unreachable,
14239 .general => |sf| {
14240 assert(t2.format.general == sf);
14241 form: switch (form) {
14242 .post_index => |post_index| {
14243 assert(post_index.base.format.general == .doubleword);
14244 return .{ .load_store = .{ .register_pair_post_indexed = .{ .integer = .{
14245 .ldp = .{
14246 .Rt = t1.alias.encode(.{}),
14247 .Rn = post_index.base.alias.encode(.{ .sp = true }),
14248 .Rt2 = t2.alias.encode(.{}),
14249 .imm7 = @intCast(@shrExact(post_index.index, @as(u2, 2) + @intFromEnum(sf))),
14250 .sf = sf,
14251 },
14252 } } } };
14253 },
14254 .pre_index => |pre_index| {
14255 assert(pre_index.base.format.general == .doubleword);
14256 return .{ .load_store = .{ .register_pair_pre_indexed = .{ .integer = .{
14257 .ldp = .{
14258 .Rt = t1.alias.encode(.{}),
14259 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
14260 .Rt2 = t2.alias.encode(.{}),
14261 .imm7 = @intCast(@shrExact(pre_index.index, @as(u2, 2) + @intFromEnum(sf))),
14262 .sf = sf,
14263 },
14264 } } } };
14265 },
14266 .signed_offset => |signed_offset| {
14267 assert(signed_offset.base.format.general == .doubleword);
14268 return .{ .load_store = .{ .register_pair_offset = .{ .integer = .{
14269 .ldp = .{
14270 .Rt = t1.alias.encode(.{}),
14271 .Rn = signed_offset.base.alias.encode(.{ .sp = true }),
14272 .Rt2 = t2.alias.encode(.{}),
14273 .imm7 = @intCast(@shrExact(signed_offset.offset, @as(u2, 2) + @intFromEnum(sf))),
14274 .sf = sf,
14275 },
14276 } } } };
14277 },
14278 .base => |base| continue :form .{ .signed_offset = .{ .base = base } },
14279 }
14280 },
14281 .scalar => |vs| {
14282 assert(t2.format.scalar == vs);
14283 form: switch (form) {
14284 .post_index => |post_index| {
14285 assert(post_index.base.format.general == .doubleword);
14286 return .{ .load_store = .{ .register_pair_post_indexed = .{ .vector = .{
14287 .ldp = .{
14288 .Rt = t1.alias.encode(.{ .V = true }),
14289 .Rn = post_index.base.alias.encode(.{ .sp = true }),
14290 .Rt2 = t2.alias.encode(.{ .V = true }),
14291 .imm7 = @intCast(@shrExact(post_index.index, @intFromEnum(vs))),
14292 .opc = .encode(vs),
14293 },
14294 } } } };
14295 },
14296 .signed_offset => |signed_offset| {
14297 assert(signed_offset.base.format.general == .doubleword);
14298 return .{ .load_store = .{ .register_pair_offset = .{ .vector = .{
14299 .ldp = .{
14300 .Rt = t1.alias.encode(.{ .V = true }),
14301 .Rn = signed_offset.base.alias.encode(.{ .sp = true }),
14302 .Rt2 = t2.alias.encode(.{ .V = true }),
14303 .imm7 = @intCast(@shrExact(signed_offset.offset, @intFromEnum(vs))),
14304 .opc = .encode(vs),
14305 },
14306 } } } };
14307 },
14308 .pre_index => |pre_index| {
14309 assert(pre_index.base.format.general == .doubleword);
14310 return .{ .load_store = .{ .register_pair_pre_indexed = .{ .vector = .{
14311 .ldp = .{
14312 .Rt = t1.alias.encode(.{ .V = true }),
14313 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
14314 .Rt2 = t2.alias.encode(.{ .V = true }),
14315 .imm7 = @intCast(@shrExact(pre_index.index, @intFromEnum(vs))),
14316 .opc = .encode(vs),
14317 },
14318 } } } };
14319 },
14320 .base => |base| continue :form .{ .signed_offset = .{ .base = base } },
14321 }
14322 },
14323 }
14324 }
14325 /// C6.2.166 LDR (immediate)
14326 /// C6.2.167 LDR (literal)
14327 /// C6.2.168 LDR (register)
14328 /// C7.2.191 LDR (immediate, SIMD&FP)
14329 /// C7.2.192 LDR (literal, SIMD&FP)
14330 /// C7.2.193 LDR (register, SIMD&FP)
14331 pub fn ldr(t: Register, form: union(enum) {
14332 post_index: struct { base: Register, index: i9 },
14333 pre_index: struct { base: Register, index: i9 },
14334 unsigned_offset: struct { base: Register, offset: u16 = 0 },
14335 base: Register,
14336 literal: i21,
14337 extended_register_explicit: struct {
14338 base: Register,
14339 index: Register,
14340 option: LoadStore.RegisterRegisterOffset.Option,
14341 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
14342 },
14343 extended_register: struct {
14344 base: Register,
14345 index: Register,
14346 extend: LoadStore.RegisterRegisterOffset.Extend,
14347 },
14348 }) Instruction {
14349 switch (t.format) {
14350 else => unreachable,
14351 .general => |sf| form: switch (form) {
14352 .post_index => |post_index| {
14353 assert(post_index.base.format.general == .doubleword);
14354 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
14355 .ldr = .{
14356 .Rt = t.alias.encode(.{}),
14357 .Rn = post_index.base.alias.encode(.{ .sp = true }),
14358 .imm9 = post_index.index,
14359 .sf = sf,
14360 },
14361 } } } };
14362 },
14363 .pre_index => |pre_index| {
14364 assert(pre_index.base.format.general == .doubleword);
14365 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
14366 .ldr = .{
14367 .Rt = t.alias.encode(.{}),
14368 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
14369 .imm9 = pre_index.index,
14370 .sf = sf,
14371 },
14372 } } } };
14373 },
14374 .unsigned_offset => |unsigned_offset| {
14375 assert(unsigned_offset.base.format.general == .doubleword);
14376 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
14377 .ldr = .{
14378 .Rt = t.alias.encode(.{}),
14379 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
14380 .imm12 = @intCast(@shrExact(unsigned_offset.offset, @as(u2, 2) + @intFromEnum(sf))),
14381 .sf = sf,
14382 },
14383 } } } };
14384 },
14385 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
14386 .literal => |offset| return .{ .load_store = .{ .register_literal = .{ .integer = .{
14387 .ldr = .{
14388 .Rt = t.alias.encode(.{}),
14389 .imm19 = @intCast(@shrExact(offset, 2)),
14390 .sf = sf,
14391 },
14392 } } } },
14393 .extended_register_explicit => |extended_register_explicit| {
14394 assert(extended_register_explicit.base.format.general == .doubleword and
14395 extended_register_explicit.index.format.general == extended_register_explicit.option.sf());
14396 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
14397 .ldr = .{
14398 .Rt = t.alias.encode(.{}),
14399 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
14400 .S = switch (sf) {
14401 .word => switch (extended_register_explicit.amount) {
14402 0 => false,
14403 2 => true,
14404 else => unreachable,
14405 },
14406 .doubleword => switch (extended_register_explicit.amount) {
14407 0 => false,
14408 3 => true,
14409 else => unreachable,
14410 },
14411 },
14412 .option = extended_register_explicit.option,
14413 .Rm = extended_register_explicit.index.alias.encode(.{}),
14414 .sf = sf,
14415 },
14416 } } } };
14417 },
14418 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
14419 .base = extended_register.base,
14420 .index = extended_register.index,
14421 .option = extended_register.extend,
14422 .amount = switch (extended_register.extend) {
14423 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
14424 },
14425 } },
14426 },
14427 .scalar => |vs| form: switch (form) {
14428 .post_index => |post_index| {
14429 assert(post_index.base.format.general == .doubleword);
14430 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .vector = .{
14431 .ldr = .{
14432 .Rt = t.alias.encode(.{ .V = true }),
14433 .Rn = post_index.base.alias.encode(.{ .sp = true }),
14434 .imm9 = post_index.index,
14435 .opc1 = .encode(vs),
14436 .size = .encode(vs),
14437 },
14438 } } } };
14439 },
14440 .pre_index => |pre_index| {
14441 assert(pre_index.base.format.general == .doubleword);
14442 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .vector = .{
14443 .ldr = .{
14444 .Rt = t.alias.encode(.{ .V = true }),
14445 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
14446 .imm9 = pre_index.index,
14447 .opc1 = .encode(vs),
14448 .size = .encode(vs),
14449 },
14450 } } } };
14451 },
14452 .unsigned_offset => |unsigned_offset| {
14453 assert(unsigned_offset.base.format.general == .doubleword);
14454 return .{ .load_store = .{ .register_unsigned_immediate = .{ .vector = .{
14455 .ldr = .{
14456 .Rt = t.alias.encode(.{ .V = true }),
14457 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
14458 .imm12 = @intCast(@shrExact(unsigned_offset.offset, @intFromEnum(vs))),
14459 .opc1 = .encode(vs),
14460 .size = .encode(vs),
14461 },
14462 } } } };
14463 },
14464 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
14465 .literal => |offset| return .{ .load_store = .{ .register_literal = .{ .vector = .{
14466 .ldr = .{
14467 .Rt = t.alias.encode(.{ .V = true }),
14468 .imm19 = @intCast(@shrExact(offset, 2)),
14469 .opc = .encode(vs),
14470 },
14471 } } } },
14472 .extended_register_explicit => |extended_register_explicit| {
14473 assert(extended_register_explicit.base.format.general == .doubleword and
14474 extended_register_explicit.index.format.general == extended_register_explicit.option.sf());
14475 return .{ .load_store = .{ .register_register_offset = .{ .vector = .{
14476 .ldr = .{
14477 .Rt = t.alias.encode(.{ .V = true }),
14478 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
14479 .S = switch (vs) {
14480 .byte => switch (extended_register_explicit.amount) {
14481 0 => false,
14482 else => unreachable,
14483 },
14484 .half => switch (extended_register_explicit.amount) {
14485 0 => false,
14486 1 => true,
14487 else => unreachable,
14488 },
14489 .single => switch (extended_register_explicit.amount) {
14490 0 => false,
14491 2 => true,
14492 else => unreachable,
14493 },
14494 .double => switch (extended_register_explicit.amount) {
14495 0 => false,
14496 3 => true,
14497 else => unreachable,
14498 },
14499 .quad => switch (extended_register_explicit.amount) {
14500 0 => false,
14501 4 => true,
14502 else => unreachable,
14503 },
14504 },
14505 .option = extended_register_explicit.option,
14506 .Rm = extended_register_explicit.index.alias.encode(.{}),
14507 .opc1 = .encode(vs),
14508 .size = .encode(vs),
14509 },
14510 } } } };
14511 },
14512 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
14513 .base = extended_register.base,
14514 .index = extended_register.index,
14515 .option = extended_register.extend,
14516 .amount = switch (extended_register.extend) {
14517 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
14518 },
14519 } },
14520 },
14521 }
14522 }
14523 /// C6.2.170 LDRB (immediate)
14524 /// C6.2.171 LDRB (register)
14525 pub fn ldrb(t: Register, form: union(enum) {
14526 post_index: struct { base: Register, index: i9 },
14527 pre_index: struct { base: Register, index: i9 },
14528 unsigned_offset: struct { base: Register, offset: u12 = 0 },
14529 base: Register,
14530 extended_register_explicit: struct {
14531 base: Register,
14532 index: Register,
14533 option: LoadStore.RegisterRegisterOffset.Option,
14534 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
14535 },
14536 extended_register: struct {
14537 base: Register,
14538 index: Register,
14539 extend: LoadStore.RegisterRegisterOffset.Extend,
14540 },
14541 }) Instruction {
14542 assert(t.format.general == .word);
14543 form: switch (form) {
14544 .post_index => |post_index| {
14545 assert(post_index.base.format.general == .doubleword);
14546 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
14547 .ldrb = .{
14548 .Rt = t.alias.encode(.{}),
14549 .Rn = post_index.base.alias.encode(.{ .sp = true }),
14550 .imm9 = post_index.index,
14551 },
14552 } } } };
14553 },
14554 .pre_index => |pre_index| {
14555 assert(pre_index.base.format.general == .doubleword);
14556 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
14557 .ldrb = .{
14558 .Rt = t.alias.encode(.{}),
14559 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
14560 .imm9 = pre_index.index,
14561 },
14562 } } } };
14563 },
14564 .unsigned_offset => |unsigned_offset| {
14565 assert(unsigned_offset.base.format.general == .doubleword);
14566 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
14567 .ldrb = .{
14568 .Rt = t.alias.encode(.{}),
14569 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
14570 .imm12 = unsigned_offset.offset,
14571 },
14572 } } } };
14573 },
14574 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
14575 .extended_register_explicit => |extended_register_explicit| {
14576 assert(extended_register_explicit.base.format.general == .doubleword and
14577 extended_register_explicit.index.format.general == extended_register_explicit.option.sf());
14578 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
14579 .ldrb = .{
14580 .Rt = t.alias.encode(.{}),
14581 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
14582 .S = switch (extended_register_explicit.amount) {
14583 0 => false,
14584 else => unreachable,
14585 },
14586 .option = extended_register_explicit.option,
14587 .Rm = extended_register_explicit.index.alias.encode(.{}),
14588 },
14589 } } } };
14590 },
14591 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
14592 .base = extended_register.base,
14593 .index = extended_register.index,
14594 .option = extended_register.extend,
14595 .amount = switch (extended_register.extend) {
14596 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
14597 },
14598 } },
14599 }
14600 }
14601 /// C6.2.172 LDRH (immediate)
14602 /// C6.2.173 LDRH (register)
14603 pub fn ldrh(t: Register, form: union(enum) {
14604 post_index: struct { base: Register, index: i9 },
14605 pre_index: struct { base: Register, index: i9 },
14606 unsigned_offset: struct { base: Register, offset: u13 = 0 },
14607 base: Register,
14608 extended_register_explicit: struct {
14609 base: Register,
14610 index: Register,
14611 option: LoadStore.RegisterRegisterOffset.Option,
14612 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
14613 },
14614 extended_register: struct {
14615 base: Register,
14616 index: Register,
14617 extend: LoadStore.RegisterRegisterOffset.Extend,
14618 },
14619 }) Instruction {
14620 assert(t.format.general == .word);
14621 form: switch (form) {
14622 .post_index => |post_index| {
14623 assert(post_index.base.format.general == .doubleword);
14624 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
14625 .ldrh = .{
14626 .Rt = t.alias.encode(.{}),
14627 .Rn = post_index.base.alias.encode(.{ .sp = true }),
14628 .imm9 = post_index.index,
14629 },
14630 } } } };
14631 },
14632 .pre_index => |pre_index| {
14633 assert(pre_index.base.format.general == .doubleword);
14634 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
14635 .ldrh = .{
14636 .Rt = t.alias.encode(.{}),
14637 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
14638 .imm9 = pre_index.index,
14639 },
14640 } } } };
14641 },
14642 .unsigned_offset => |unsigned_offset| {
14643 assert(unsigned_offset.base.format.general == .doubleword);
14644 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
14645 .ldrh = .{
14646 .Rt = t.alias.encode(.{}),
14647 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
14648 .imm12 = @intCast(@shrExact(unsigned_offset.offset, 1)),
14649 },
14650 } } } };
14651 },
14652 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
14653 .extended_register_explicit => |extended_register_explicit| {
14654 assert(extended_register_explicit.base.format.general == .doubleword and
14655 extended_register_explicit.index.format.general == extended_register_explicit.option.sf());
14656 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
14657 .ldrh = .{
14658 .Rt = t.alias.encode(.{}),
14659 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
14660 .S = switch (extended_register_explicit.amount) {
14661 0 => false,
14662 1 => true,
14663 else => unreachable,
14664 },
14665 .option = extended_register_explicit.option,
14666 .Rm = extended_register_explicit.index.alias.encode(.{}),
14667 },
14668 } } } };
14669 },
14670 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
14671 .base = extended_register.base,
14672 .index = extended_register.index,
14673 .option = extended_register.extend,
14674 .amount = switch (extended_register.extend) {
14675 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
14676 },
14677 } },
14678 }
14679 }
14680 /// C6.2.174 LDRSB (immediate)
14681 /// C6.2.175 LDRSB (register)
14682 pub fn ldrsb(t: Register, form: union(enum) {
14683 post_index: struct { base: Register, index: i9 },
14684 pre_index: struct { base: Register, index: i9 },
14685 unsigned_offset: struct { base: Register, offset: u12 = 0 },
14686 base: Register,
14687 extended_register_explicit: struct {
14688 base: Register,
14689 index: Register,
14690 option: LoadStore.RegisterRegisterOffset.Option,
14691 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
14692 },
14693 extended_register: struct {
14694 base: Register,
14695 index: Register,
14696 extend: LoadStore.RegisterRegisterOffset.Extend,
14697 },
14698 }) Instruction {
14699 const sf = t.format.general;
14700 form: switch (form) {
14701 .post_index => |post_index| {
14702 assert(post_index.base.format.general == .doubleword);
14703 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
14704 .ldrsb = .{
14705 .Rt = t.alias.encode(.{}),
14706 .Rn = post_index.base.alias.encode(.{ .sp = true }),
14707 .imm9 = post_index.index,
14708 .opc0 = ~@intFromEnum(sf),
14709 },
14710 } } } };
14711 },
14712 .pre_index => |pre_index| {
14713 assert(pre_index.base.format.general == .doubleword);
14714 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
14715 .ldrsb = .{
14716 .Rt = t.alias.encode(.{}),
14717 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
14718 .imm9 = pre_index.index,
14719 .opc0 = ~@intFromEnum(sf),
14720 },
14721 } } } };
14722 },
14723 .unsigned_offset => |unsigned_offset| {
14724 assert(unsigned_offset.base.format.general == .doubleword);
14725 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
14726 .ldrsb = .{
14727 .Rt = t.alias.encode(.{}),
14728 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
14729 .imm12 = unsigned_offset.offset,
14730 .opc0 = ~@intFromEnum(sf),
14731 },
14732 } } } };
14733 },
14734 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
14735 .extended_register_explicit => |extended_register_explicit| {
14736 assert(extended_register_explicit.base.format.general == .doubleword and
14737 extended_register_explicit.index.format.general == extended_register_explicit.option.sf());
14738 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
14739 .ldrsb = .{
14740 .Rt = t.alias.encode(.{}),
14741 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
14742 .S = switch (extended_register_explicit.amount) {
14743 0 => false,
14744 else => unreachable,
14745 },
14746 .option = extended_register_explicit.option,
14747 .Rm = extended_register_explicit.index.alias.encode(.{}),
14748 .opc0 = ~@intFromEnum(sf),
14749 },
14750 } } } };
14751 },
14752 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
14753 .base = extended_register.base,
14754 .index = extended_register.index,
14755 .option = extended_register.extend,
14756 .amount = switch (extended_register.extend) {
14757 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
14758 },
14759 } },
14760 }
14761 }
14762 /// C6.2.176 LDRSH (immediate)
14763 /// C6.2.177 LDRSH (register)
14764 pub fn ldrsh(t: Register, form: union(enum) {
14765 post_index: struct { base: Register, index: i9 },
14766 pre_index: struct { base: Register, index: i9 },
14767 unsigned_offset: struct { base: Register, offset: u13 = 0 },
14768 base: Register,
14769 extended_register_explicit: struct {
14770 base: Register,
14771 index: Register,
14772 option: LoadStore.RegisterRegisterOffset.Option,
14773 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
14774 },
14775 extended_register: struct {
14776 base: Register,
14777 index: Register,
14778 extend: LoadStore.RegisterRegisterOffset.Extend,
14779 },
14780 }) Instruction {
14781 const sf = t.format.general;
14782 form: switch (form) {
14783 .post_index => |post_index| {
14784 assert(post_index.base.format.general == .doubleword);
14785 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
14786 .ldrsh = .{
14787 .Rt = t.alias.encode(.{}),
14788 .Rn = post_index.base.alias.encode(.{ .sp = true }),
14789 .imm9 = post_index.index,
14790 .opc0 = ~@intFromEnum(sf),
14791 },
14792 } } } };
14793 },
14794 .pre_index => |pre_index| {
14795 assert(pre_index.base.format.general == .doubleword);
14796 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
14797 .ldrsh = .{
14798 .Rt = t.alias.encode(.{}),
14799 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
14800 .imm9 = pre_index.index,
14801 .opc0 = ~@intFromEnum(sf),
14802 },
14803 } } } };
14804 },
14805 .unsigned_offset => |unsigned_offset| {
14806 assert(unsigned_offset.base.format.general == .doubleword);
14807 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
14808 .ldrsh = .{
14809 .Rt = t.alias.encode(.{}),
14810 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
14811 .imm12 = @intCast(@shrExact(unsigned_offset.offset, 1)),
14812 .opc0 = ~@intFromEnum(sf),
14813 },
14814 } } } };
14815 },
14816 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
14817 .extended_register_explicit => |extended_register_explicit| {
14818 assert(extended_register_explicit.base.format.general == .doubleword and
14819 extended_register_explicit.index.format.general == extended_register_explicit.option.sf());
14820 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
14821 .ldrsh = .{
14822 .Rt = t.alias.encode(.{}),
14823 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
14824 .S = switch (extended_register_explicit.amount) {
14825 0 => false,
14826 1 => true,
14827 else => unreachable,
14828 },
14829 .option = extended_register_explicit.option,
14830 .Rm = extended_register_explicit.index.alias.encode(.{}),
14831 .opc0 = ~@intFromEnum(sf),
14832 },
14833 } } } };
14834 },
14835 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
14836 .base = extended_register.base,
14837 .index = extended_register.index,
14838 .option = extended_register.extend,
14839 .amount = switch (extended_register.extend) {
14840 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
14841 },
14842 } },
14843 }
14844 }
14845 /// C6.2.178 LDRSW (immediate)
14846 /// C6.2.179 LDRSW (literal)
14847 /// C6.2.180 LDRSW (register)
14848 pub fn ldrsw(t: Register, form: union(enum) {
14849 post_index: struct { base: Register, index: i9 },
14850 pre_index: struct { base: Register, index: i9 },
14851 unsigned_offset: struct { base: Register, offset: u14 = 0 },
14852 base: Register,
14853 literal: i21,
14854 extended_register_explicit: struct {
14855 base: Register,
14856 index: Register,
14857 option: LoadStore.RegisterRegisterOffset.Option,
14858 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
14859 },
14860 extended_register: struct {
14861 base: Register,
14862 index: Register,
14863 extend: LoadStore.RegisterRegisterOffset.Extend,
14864 },
14865 }) Instruction {
14866 assert(t.format.general == .doubleword);
14867 form: switch (form) {
14868 .post_index => |post_index| {
14869 assert(post_index.base.format.general == .doubleword);
14870 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
14871 .ldrsw = .{
14872 .Rt = t.alias.encode(.{}),
14873 .Rn = post_index.base.alias.encode(.{ .sp = true }),
14874 .imm9 = post_index.index,
14875 },
14876 } } } };
14877 },
14878 .pre_index => |pre_index| {
14879 assert(pre_index.base.format.general == .doubleword);
14880 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
14881 .ldrsw = .{
14882 .Rt = t.alias.encode(.{}),
14883 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
14884 .imm9 = pre_index.index,
14885 },
14886 } } } };
14887 },
14888 .unsigned_offset => |unsigned_offset| {
14889 assert(unsigned_offset.base.format.general == .doubleword);
14890 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
14891 .ldrsw = .{
14892 .Rt = t.alias.encode(.{}),
14893 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
14894 .imm12 = @intCast(@shrExact(unsigned_offset.offset, 2)),
14895 },
14896 } } } };
14897 },
14898 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
14899 .literal => |offset| return .{ .load_store = .{ .register_literal = .{ .integer = .{
14900 .ldrsw = .{
14901 .Rt = t.alias.encode(.{}),
14902 .imm19 = @intCast(@shrExact(offset, 2)),
14903 },
14904 } } } },
14905 .extended_register_explicit => |extended_register_explicit| {
14906 assert(extended_register_explicit.base.format.general == .doubleword and
14907 extended_register_explicit.index.format.general == extended_register_explicit.option.sf());
14908 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
14909 .ldrsw = .{
14910 .Rt = t.alias.encode(.{}),
14911 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
14912 .S = switch (extended_register_explicit.amount) {
14913 0 => false,
14914 2 => true,
14915 else => unreachable,
14916 },
14917 .option = extended_register_explicit.option,
14918 .Rm = extended_register_explicit.index.alias.encode(.{}),
14919 },
14920 } } } };
14921 },
14922 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
14923 .base = extended_register.base,
14924 .index = extended_register.index,
14925 .option = extended_register.extend,
14926 .amount = switch (extended_register.extend) {
14927 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
14928 },
14929 } },
14930 }
14931 }
14932 /// C6.2.202 LDUR
14933 /// C7.2.194 LDUR (SIMD&FP)
14934 pub fn ldur(t: Register, n: Register, simm: i9) Instruction {
14935 assert(n.format.general == .doubleword);
14936 switch (t.format) {
14937 else => unreachable,
14938 .general => |sf| return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
14939 .ldur = .{
14940 .Rt = t.alias.encode(.{}),
14941 .Rn = n.alias.encode(.{ .sp = true }),
14942 .imm9 = simm,
14943 .sf = sf,
14944 },
14945 } } } },
14946 .scalar => |vs| return .{ .load_store = .{ .register_unscaled_immediate = .{ .vector = .{
14947 .ldur = .{
14948 .Rt = t.alias.encode(.{ .V = true }),
14949 .Rn = n.alias.encode(.{ .sp = true }),
14950 .imm9 = simm,
14951 .opc1 = .encode(vs),
14952 .size = .encode(vs),
14953 },
14954 } } } },
14955 }
14956 }
14957 /// C6.2.203 LDURB
14958 pub fn ldurb(t: Register, n: Register, simm: i9) Instruction {
14959 assert(t.format.general == .word and n.format.general == .doubleword);
14960 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
14961 .ldurb = .{
14962 .Rt = t.alias.encode(.{}),
14963 .Rn = n.alias.encode(.{ .sp = true }),
14964 .imm9 = simm,
14965 },
14966 } } } };
14967 }
14968 /// C6.2.204 LDURH
14969 pub fn ldurh(t: Register, n: Register, simm: i9) Instruction {
14970 assert(t.format.general == .word and n.format.general == .doubleword);
14971 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
14972 .ldurh = .{
14973 .Rt = t.alias.encode(.{}),
14974 .Rn = n.alias.encode(.{ .sp = true }),
14975 .imm9 = simm,
14976 },
14977 } } } };
14978 }
14979 /// C6.2.205 LDURSB
14980 pub fn ldursb(t: Register, n: Register, simm: i9) Instruction {
14981 assert(n.format.general == .doubleword);
14982 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
14983 .ldursb = .{
14984 .Rt = t.alias.encode(.{}),
14985 .Rn = n.alias.encode(.{ .sp = true }),
14986 .imm9 = simm,
14987 .opc0 = ~@intFromEnum(t.format.general),
14988 },
14989 } } } };
14990 }
14991 /// C6.2.206 LDURSH
14992 pub fn ldursh(t: Register, n: Register, simm: i9) Instruction {
14993 assert(n.format.general == .doubleword);
14994 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
14995 .ldursh = .{
14996 .Rt = t.alias.encode(.{}),
14997 .Rn = n.alias.encode(.{ .sp = true }),
14998 .imm9 = simm,
14999 .opc0 = ~@intFromEnum(t.format.general),
15000 },
15001 } } } };
15002 }
15003 /// C6.2.207 LDURSW
15004 pub fn ldursw(t: Register, n: Register, simm: i9) Instruction {
15005 assert(t.format.general == .doubleword and n.format.general == .doubleword);
15006 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
15007 .ldursw = .{
15008 .Rt = t.alias.encode(.{}),
15009 .Rn = n.alias.encode(.{ .sp = true }),
15010 .imm9 = simm,
15011 },
15012 } } } };
15013 }
15014 /// C6.2.214 LSLV
15015 pub fn lslv(d: Register, n: Register, m: Register) Instruction {
15016 const sf = d.format.general;
15017 assert(n.format.general == sf and m.format.general == sf);
15018 return .{ .data_processing_register = .{ .data_processing_two_source = .{
15019 .lslv = .{
15020 .Rd = d.alias.encode(.{}),
15021 .Rn = n.alias.encode(.{}),
15022 .Rm = m.alias.encode(.{}),
15023 .sf = sf,
15024 },
15025 } } };
15026 }
15027 /// C6.2.217 LSRV
15028 pub fn lsrv(d: Register, n: Register, m: Register) Instruction {
15029 const sf = d.format.general;
15030 assert(n.format.general == sf and m.format.general == sf);
15031 return .{ .data_processing_register = .{ .data_processing_two_source = .{
15032 .lsrv = .{
15033 .Rd = d.alias.encode(.{}),
15034 .Rn = n.alias.encode(.{}),
15035 .Rm = m.alias.encode(.{}),
15036 .sf = sf,
15037 },
15038 } } };
15039 }
15040 /// C6.2.218 MADD
15041 pub fn madd(d: Register, n: Register, m: Register, a: Register) Instruction {
15042 const sf = d.format.general;
15043 assert(n.format.general == sf and m.format.general == sf and a.format.general == sf);
15044 return .{ .data_processing_register = .{ .data_processing_three_source = .{
15045 .madd = .{
15046 .Rd = d.alias.encode(.{}),
15047 .Rn = n.alias.encode(.{}),
15048 .Ra = a.alias.encode(.{}),
15049 .Rm = m.alias.encode(.{}),
15050 .sf = sf,
15051 },
15052 } } };
15053 }
15054 /// C7.2.204 MOVI
15055 pub fn movi(d: Register, imm8: u8, shift: union(enum) { lsl: u5, msl: u5, replicate }) Instruction {
15056 const arrangement = switch (d.format) {
15057 else => unreachable,
15058 .scalar => |vs| switch (vs) {
15059 else => unreachable,
15060 .double => .@"1d",
15061 },
15062 .vector => |arrangement| switch (arrangement) {
15063 .@"1d" => unreachable,
15064 else => arrangement,
15065 },
15066 };
15067 return .{ .data_processing_vector = .{ .simd_modified_immediate = .{
15068 .movi = .{
15069 .Rd = d.alias.encode(.{ .V = true }),
15070 .imm5 = @truncate(imm8 >> 0),
15071 .cmode = switch (shift) {
15072 .lsl => |amount| switch (arrangement) {
15073 else => unreachable,
15074 .@"8b", .@"16b" => @as(u4, 0b1110) |
15075 @as(u4, @as(u0, @intCast(@shrExact(amount, 3)))) << 1,
15076 .@"4h", .@"8h" => @as(u4, 0b1000) |
15077 @as(u4, @as(u1, @intCast(@shrExact(amount, 3)))) << 1,
15078 .@"2s", .@"4s" => @as(u4, 0b0000) |
15079 @as(u4, @as(u2, @intCast(@shrExact(amount, 3)))) << 1,
15080 },
15081 .msl => |amount| switch (arrangement) {
15082 else => unreachable,
15083 .@"2s", .@"4s" => @as(u4, 0b1100) |
15084 @as(u4, @as(u1, @intCast(@shrExact(amount, 3) - 1))) << 0,
15085 },
15086 .replicate => switch (arrangement) {
15087 else => unreachable,
15088 .@"1d", .@"2d" => 0b1110,
15089 },
15090 },
15091 .imm3 = @intCast(imm8 >> 5),
15092 .op = switch (shift) {
15093 .lsl, .msl => 0b0,
15094 .replicate => 0b1,
15095 },
15096 .Q = arrangement.size(),
15097 },
15098 } } };
15099 }
15100 /// C6.2.225 MOVK
15101 pub fn movk(
15102 d: Register,
15103 imm: u16,
15104 shift: struct { lsl: DataProcessingImmediate.MoveWideImmediate.Hw = .@"0" },
15105 ) Instruction {
15106 const sf = d.format.general;
15107 assert(sf == .doubleword or shift.lsl.sf() == .word);
15108 return .{ .data_processing_immediate = .{ .move_wide_immediate = .{
15109 .movk = .{
15110 .Rd = d.alias.encode(.{}),
15111 .imm16 = imm,
15112 .hw = shift.lsl,
15113 .sf = sf,
15114 },
15115 } } };
15116 }
15117 /// C6.2.226 MOVN
15118 pub fn movn(
15119 d: Register,
15120 imm: u16,
15121 shift: struct { lsl: DataProcessingImmediate.MoveWideImmediate.Hw = .@"0" },
15122 ) Instruction {
15123 const sf = d.format.general;
15124 assert(sf == .doubleword or shift.lsl.sf() == .word);
15125 return .{ .data_processing_immediate = .{ .move_wide_immediate = .{
15126 .movn = .{
15127 .Rd = d.alias.encode(.{}),
15128 .imm16 = imm,
15129 .hw = shift.lsl,
15130 .sf = sf,
15131 },
15132 } } };
15133 }
15134 /// C6.2.227 MOVZ
15135 pub fn movz(
15136 d: Register,
15137 imm: u16,
15138 shift: struct { lsl: DataProcessingImmediate.MoveWideImmediate.Hw = .@"0" },
15139 ) Instruction {
15140 const sf = d.format.general;
15141 assert(sf == .doubleword or shift.lsl.sf() == .word);
15142 return .{ .data_processing_immediate = .{ .move_wide_immediate = .{
15143 .movz = .{
15144 .Rd = d.alias.encode(.{}),
15145 .imm16 = imm,
15146 .hw = shift.lsl,
15147 .sf = sf,
15148 },
15149 } } };
15150 }
15151 /// C6.2.228 MRS
15152 pub fn mrs(t: Register, systemreg: Register.System) Instruction {
15153 assert(t.format.general == .doubleword and systemreg.op0 >= 0b10);
15154 return .{ .branch_exception_generating_system = .{ .system_register_move = .{
15155 .mrs = .{
15156 .Rt = t.alias.encode(.{}),
15157 .systemreg = systemreg,
15158 },
15159 } } };
15160 }
15161 /// C6.2.230 MSR (register)
15162 pub fn msr(systemreg: Register.System, t: Register) Instruction {
15163 assert(systemreg.op0 >= 0b10 and t.format.general == .doubleword);
15164 return .{ .branch_exception_generating_system = .{ .system_register_move = .{
15165 .msr = .{
15166 .Rt = t.alias.encode(.{}),
15167 .systemreg = systemreg,
15168 },
15169 } } };
15170 }
15171 /// C6.2.231 MSUB
15172 pub fn msub(d: Register, n: Register, m: Register, a: Register) Instruction {
15173 const sf = d.format.general;
15174 assert(n.format.general == sf and m.format.general == sf and a.format.general == sf);
15175 return .{ .data_processing_register = .{ .data_processing_three_source = .{
15176 .msub = .{
15177 .Rd = d.alias.encode(.{}),
15178 .Rn = n.alias.encode(.{}),
15179 .Ra = a.alias.encode(.{}),
15180 .Rm = m.alias.encode(.{}),
15181 .sf = sf,
15182 },
15183 } } };
15184 }
15185 /// C7.2.209 NEG (vector)
15186 pub fn neg(d: Register, n: Register) Instruction {
15187 switch (d.format) {
15188 else => unreachable,
15189 .scalar => |elem_size| {
15190 assert(elem_size == .double and elem_size == n.format.scalar);
15191 return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
15192 .neg = .{
15193 .Rd = d.alias.encode(.{ .V = true }),
15194 .Rn = n.alias.encode(.{ .V = true }),
15195 .size = .fromScalarSize(elem_size),
15196 },
15197 } } };
15198 },
15199 .vector => |arrangement| {
15200 assert(arrangement != .@"1d" and n.format.vector == arrangement);
15201 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
15202 .neg = .{
15203 .Rd = d.alias.encode(.{ .V = true }),
15204 .Rn = n.alias.encode(.{ .V = true }),
15205 .size = arrangement.elemSize(),
15206 .Q = arrangement.size(),
15207 },
15208 } } };
15209 },
15210 }
15211 }
15212 /// C6.2.238 NOP
15213 pub fn nop() Instruction {
15214 return .{ .branch_exception_generating_system = .{ .hints = .{
15215 .nop = .{},
15216 } } };
15217 }
15218 /// C7.2.210 NOT
15219 pub fn not(d: Register, n: Register) Instruction {
15220 const arrangement = d.format.vector;
15221 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement);
15222 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
15223 .not = .{
15224 .Rd = d.alias.encode(.{ .V = true }),
15225 .Rn = n.alias.encode(.{ .V = true }),
15226 .size = arrangement.elemSize(),
15227 .Q = arrangement.size(),
15228 },
15229 } } };
15230 }
15231 /// C6.2.239 ORN (shifted register)
15232 /// C7.2.211 ORN (vector)
15233 pub fn orn(d: Register, n: Register, form: union(enum) {
15234 register: Register,
15235 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
15236 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
15237 }) Instruction {
15238 switch (d.format) {
15239 else => unreachable,
15240 .general => |sf| {
15241 assert(n.format.general == sf);
15242 form: switch (form) {
15243 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
15244 .shifted_register_explicit => |shifted_register_explicit| {
15245 assert(shifted_register_explicit.register.format.general == sf);
15246 return .{ .data_processing_register = .{ .logical_shifted_register = .{
15247 .orn = .{
15248 .Rd = d.alias.encode(.{}),
15249 .Rn = n.alias.encode(.{}),
15250 .imm6 = switch (sf) {
15251 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
15252 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
15253 },
15254 .Rm = shifted_register_explicit.register.alias.encode(.{}),
15255 .shift = shifted_register_explicit.shift,
15256 .sf = sf,
15257 },
15258 } } };
15259 },
15260 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
15261 .register = shifted_register.register,
15262 .shift = shifted_register.shift,
15263 .amount = switch (shifted_register.shift) {
15264 .lsl, .lsr, .asr, .ror => |amount| amount,
15265 },
15266 } },
15267 }
15268 },
15269 .vector => |arrangement| {
15270 const m = form.register;
15271 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
15272 return .{ .data_processing_vector = .{ .simd_three_same = .{
15273 .orn = .{
15274 .Rd = d.alias.encode(.{ .V = true }),
15275 .Rn = n.alias.encode(.{ .V = true }),
15276 .Rm = m.alias.encode(.{ .V = true }),
15277 .Q = arrangement.size(),
15278 },
15279 } } };
15280 },
15281 }
15282 }
15283 /// C6.2.240 ORR (immediate)
15284 /// C6.2.241 ORR (shifted register)
15285 /// C7.2.212 ORR (vector, immediate)
15286 /// C7.2.213 ORR (vector, register)
15287 pub fn orr(d: Register, n: Register, form: union(enum) {
15288 immediate: DataProcessingImmediate.Bitmask,
15289 shifted_immediate: struct { immediate: u8, lsl: u5 = 0 },
15290 register: Register,
15291 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
15292 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
15293 }) Instruction {
15294 switch (d.format) {
15295 else => unreachable,
15296 .general => |sf| {
15297 assert(n.format.general == sf);
15298 form: switch (form) {
15299 .immediate => |bitmask| {
15300 assert(bitmask.validImmediate(sf));
15301 return .{ .data_processing_immediate = .{ .logical_immediate = .{
15302 .orr = .{
15303 .Rd = d.alias.encode(.{ .sp = true }),
15304 .Rn = n.alias.encode(.{}),
15305 .imm = bitmask,
15306 .sf = sf,
15307 },
15308 } } };
15309 },
15310 .shifted_immediate => unreachable,
15311 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
15312 .shifted_register_explicit => |shifted_register_explicit| {
15313 assert(shifted_register_explicit.register.format.general == sf);
15314 return .{ .data_processing_register = .{ .logical_shifted_register = .{
15315 .orr = .{
15316 .Rd = d.alias.encode(.{}),
15317 .Rn = n.alias.encode(.{}),
15318 .imm6 = switch (sf) {
15319 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
15320 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
15321 },
15322 .Rm = shifted_register_explicit.register.alias.encode(.{}),
15323 .shift = shifted_register_explicit.shift,
15324 .sf = sf,
15325 },
15326 } } };
15327 },
15328 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
15329 .register = shifted_register.register,
15330 .shift = shifted_register.shift,
15331 .amount = switch (shifted_register.shift) {
15332 .lsl, .lsr, .asr, .ror => |amount| amount,
15333 },
15334 } },
15335 }
15336 },
15337 .vector => |arrangement| switch (form) {
15338 else => unreachable,
15339 .shifted_immediate => |shifted_immediate| {
15340 assert(n.alias == d.alias and n.format.vector == arrangement);
15341 return .{ .data_processing_vector = .{ .simd_modified_immediate = .{
15342 .orr = .{
15343 .Rd = d.alias.encode(.{ .V = true }),
15344 .imm5 = @truncate(shifted_immediate.immediate >> 0),
15345 .cmode = switch (arrangement) {
15346 else => unreachable,
15347 .@"4h", .@"8h" => @as(u3, 0b100) |
15348 @as(u3, @as(u1, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0,
15349 .@"2s", .@"4s" => @as(u3, 0b000) |
15350 @as(u3, @as(u2, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0,
15351 },
15352 .imm3 = @intCast(shifted_immediate.immediate >> 5),
15353 .Q = arrangement.size(),
15354 },
15355 } } };
15356 },
15357 .register => |m| {
15358 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
15359 return .{ .data_processing_vector = .{ .simd_three_same = .{
15360 .orr = .{
15361 .Rd = d.alias.encode(.{ .V = true }),
15362 .Rn = n.alias.encode(.{ .V = true }),
15363 .Rm = m.alias.encode(.{ .V = true }),
15364 .Q = arrangement.size(),
15365 },
15366 } } };
15367 },
15368 },
15369 }
15370 }
15371 /// C6.2.247 PRFM (immediate)
15372 /// C6.2.248 PRFM (literal)
15373 /// C6.2.249 PRFM (register)
15374 pub fn prfm(prfop: LoadStore.PrfOp, form: union(enum) {
15375 unsigned_offset: struct { base: Register, offset: u15 = 0 },
15376 base: Register,
15377 literal: i21,
15378 extended_register_explicit: struct {
15379 base: Register,
15380 index: Register,
15381 option: LoadStore.RegisterRegisterOffset.Option,
15382 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
15383 },
15384 extended_register: struct {
15385 base: Register,
15386 index: Register,
15387 extend: LoadStore.RegisterRegisterOffset.Extend,
15388 },
15389 }) Instruction {
15390 form: switch (form) {
15391 .unsigned_offset => |unsigned_offset| {
15392 assert(unsigned_offset.base.format.general == .doubleword);
15393 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
15394 .prfm = .{
15395 .prfop = prfop,
15396 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
15397 .imm12 = @intCast(@shrExact(unsigned_offset.offset, 3)),
15398 },
15399 } } } };
15400 },
15401 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
15402 .literal => |offset| return .{ .load_store = .{ .register_literal = .{ .integer = .{
15403 .prfm = .{
15404 .prfop = prfop,
15405 .imm19 = @intCast(@shrExact(offset, 2)),
15406 },
15407 } } } },
15408 .extended_register_explicit => |extended_register_explicit| {
15409 assert(extended_register_explicit.base.format.general == .doubleword and
15410 extended_register_explicit.index.format.general == extended_register_explicit.option.sf());
15411 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
15412 .prfm = .{
15413 .prfop = prfop,
15414 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
15415 .S = switch (extended_register_explicit.amount) {
15416 0 => false,
15417 3 => true,
15418 else => unreachable,
15419 },
15420 .option = extended_register_explicit.option,
15421 .Rm = extended_register_explicit.index.alias.encode(.{}),
15422 },
15423 } } } };
15424 },
15425 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
15426 .base = extended_register.base,
15427 .index = extended_register.index,
15428 .option = extended_register.extend,
15429 .amount = switch (extended_register.extend) {
15430 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
15431 },
15432 } },
15433 }
15434 }
15435 /// C6.2.253 RBIT
15436 pub fn rbit(d: Register, n: Register) Instruction {
15437 const sf = d.format.general;
15438 assert(n.format.general == sf);
15439 return .{ .data_processing_register = .{ .data_processing_one_source = .{
15440 .rbit = .{
15441 .Rd = d.alias.encode(.{}),
15442 .Rn = n.alias.encode(.{}),
15443 .sf = sf,
15444 },
15445 } } };
15446 }
15447 /// C6.2.254 RET
15448 pub fn ret(n: Register) Instruction {
15449 assert(n.format.general == .doubleword);
15450 return .{ .branch_exception_generating_system = .{ .unconditional_branch_register = .{
15451 .ret = .{ .Rn = n.alias.encode(.{}) },
15452 } } };
15453 }
15454 /// C6.2.256 REV
15455 pub fn rev(d: Register, n: Register) Instruction {
15456 const sf = d.format.general;
15457 assert(n.format.general == sf);
15458 return .{ .data_processing_register = .{ .data_processing_one_source = .{
15459 .rev = .{
15460 .Rd = d.alias.encode(.{}),
15461 .Rn = n.alias.encode(.{}),
15462 .opc0 = sf,
15463 .sf = sf,
15464 },
15465 } } };
15466 }
15467 /// C6.2.257 REV16
15468 pub fn rev16(d: Register, n: Register) Instruction {
15469 const sf = d.format.general;
15470 assert(n.format.general == sf);
15471 return .{ .data_processing_register = .{ .data_processing_one_source = .{
15472 .rev16 = .{
15473 .Rd = d.alias.encode(.{}),
15474 .Rn = n.alias.encode(.{}),
15475 .sf = sf,
15476 },
15477 } } };
15478 }
15479 /// C6.2.258 REV32
15480 pub fn rev32(d: Register, n: Register) Instruction {
15481 assert(d.format.general == .doubleword and n.format.general == .doubleword);
15482 return .{ .data_processing_register = .{ .data_processing_one_source = .{
15483 .rev32 = .{
15484 .Rd = d.alias.encode(.{}),
15485 .Rn = n.alias.encode(.{}),
15486 },
15487 } } };
15488 }
15489 /// C6.2.263 RORV
15490 pub fn rorv(d: Register, n: Register, m: Register) Instruction {
15491 const sf = d.format.general;
15492 assert(n.format.general == sf and m.format.general == sf);
15493 return .{ .data_processing_register = .{ .data_processing_two_source = .{
15494 .rorv = .{
15495 .Rd = d.alias.encode(.{}),
15496 .Rn = n.alias.encode(.{}),
15497 .Rm = m.alias.encode(.{}),
15498 .sf = sf,
15499 },
15500 } } };
15501 }
15502 /// C6.2.264 SB
15503 pub fn sb() Instruction {
15504 return .{ .branch_exception_generating_system = .{ .barriers = .{
15505 .sb = .{},
15506 } } };
15507 }
15508 /// C6.2.265 SBC
15509 pub fn sbc(d: Register, n: Register, m: Register) Instruction {
15510 const sf = d.format.general;
15511 assert(n.format.general == sf and m.format.general == sf);
15512 return .{ .data_processing_register = .{ .add_subtract_with_carry = .{
15513 .sbc = .{
15514 .Rd = d.alias.encode(.{}),
15515 .Rn = n.alias.encode(.{}),
15516 .Rm = m.alias.encode(.{}),
15517 .sf = sf,
15518 },
15519 } } };
15520 }
15521 /// C6.2.266 SBCS
15522 pub fn sbcs(d: Register, n: Register, m: Register) Instruction {
15523 const sf = d.format.general;
15524 assert(n.format.general == sf and m.format.general == sf);
15525 return .{ .data_processing_register = .{ .add_subtract_with_carry = .{
15526 .sbcs = .{
15527 .Rd = d.alias.encode(.{}),
15528 .Rn = n.alias.encode(.{}),
15529 .Rm = m.alias.encode(.{}),
15530 .sf = sf,
15531 },
15532 } } };
15533 }
15534 /// C6.2.268 SBFM
15535 pub fn sbfm(d: Register, n: Register, bitmask: DataProcessingImmediate.Bitmask) Instruction {
15536 const sf = d.format.general;
15537 assert(n.format.general == sf and bitmask.validBitfield(sf));
15538 return .{ .data_processing_immediate = .{ .bitfield = .{
15539 .sbfm = .{
15540 .Rd = d.alias.encode(.{}),
15541 .Rn = n.alias.encode(.{}),
15542 .imm = bitmask,
15543 .sf = sf,
15544 },
15545 } } };
15546 }
15547 /// C7.2.234 SCVTF (vector, integer)
15548 /// C7.2.236 SCVTF (scalar, integer)
15549 pub fn scvtf(d: Register, n: Register) Instruction {
15550 switch (d.format) {
15551 else => unreachable,
15552 .scalar => |ftype| switch (n.format) {
15553 else => unreachable,
15554 .scalar => |elem_size| {
15555 assert(ftype == elem_size);
15556 switch (ftype) {
15557 else => unreachable,
15558 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
15559 .scvtf = .{
15560 .Rd = d.alias.encode(.{ .V = true }),
15561 .Rn = n.alias.encode(.{ .V = true }),
15562 },
15563 } } },
15564 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
15565 .scvtf = .{
15566 .Rd = d.alias.encode(.{ .V = true }),
15567 .Rn = n.alias.encode(.{ .V = true }),
15568 .sz = .fromScalarSize(ftype),
15569 },
15570 } } },
15571 }
15572 },
15573 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
15574 .scvtf = .{
15575 .Rd = d.alias.encode(.{ .V = true }),
15576 .Rn = n.alias.encode(.{}),
15577 .ftype = .fromScalarSize(ftype),
15578 .sf = sf,
15579 },
15580 } } },
15581 },
15582 .vector => |arrangement| {
15583 assert(arrangement != .@"1d" and n.format.vector == arrangement);
15584 switch (arrangement.elemSize()) {
15585 else => unreachable,
15586 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
15587 .scvtf = .{
15588 .Rd = d.alias.encode(.{ .V = true }),
15589 .Rn = n.alias.encode(.{ .V = true }),
15590 .Q = arrangement.size(),
15591 },
15592 } } },
15593 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
15594 .scvtf = .{
15595 .Rd = d.alias.encode(.{ .V = true }),
15596 .Rn = n.alias.encode(.{ .V = true }),
15597 .sz = arrangement.elemSz(),
15598 .Q = arrangement.size(),
15599 },
15600 } } },
15601 }
15602 },
15603 }
15604 }
15605 /// C6.2.270 SDIV
15606 pub fn sdiv(d: Register, n: Register, m: Register) Instruction {
15607 const sf = d.format.general;
15608 assert(n.format.general == sf and m.format.general == sf);
15609 return .{ .data_processing_register = .{ .data_processing_two_source = .{
15610 .sdiv = .{
15611 .Rd = d.alias.encode(.{}),
15612 .Rn = n.alias.encode(.{}),
15613 .Rm = m.alias.encode(.{}),
15614 .sf = sf,
15615 },
15616 } } };
15617 }
15618 /// C6.2.280 SEV
15619 pub fn sev() Instruction {
15620 return .{ .branch_exception_generating_system = .{ .hints = .{
15621 .sev = .{},
15622 } } };
15623 }
15624 /// C6.2.281 SEVL
15625 pub fn sevl() Instruction {
15626 return .{ .branch_exception_generating_system = .{ .hints = .{
15627 .sevl = .{},
15628 } } };
15629 }
15630 /// C6.2.282 SMADDL
15631 pub fn smaddl(d: Register, n: Register, m: Register, a: Register) Instruction {
15632 assert(d.format.general == .doubleword and n.format.general == .word and m.format.general == .word and a.format.general == .doubleword);
15633 return .{ .data_processing_register = .{ .data_processing_three_source = .{
15634 .smaddl = .{
15635 .Rd = d.alias.encode(.{}),
15636 .Rn = n.alias.encode(.{}),
15637 .Ra = a.alias.encode(.{}),
15638 .Rm = m.alias.encode(.{}),
15639 },
15640 } } };
15641 }
15642 /// C6.2.283 SMC
15643 pub fn smc(imm: u16) Instruction {
15644 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
15645 .smc = .{ .imm16 = imm },
15646 } } };
15647 }
15648 /// C7.2.279 SMOV
15649 pub fn smov(d: Register, n: Register) Instruction {
15650 const sf = d.format.general;
15651 const vs = n.format.element.size;
15652 switch (vs) {
15653 else => unreachable,
15654 .byte, .half => {},
15655 .single => assert(sf == .doubleword),
15656 }
15657 return .{ .data_processing_vector = .{ .simd_copy = .{
15658 .smov = .{
15659 .Rd = d.alias.encode(.{}),
15660 .Rn = n.alias.encode(.{ .V = true }),
15661 .imm5 = switch (vs) {
15662 else => unreachable,
15663 .byte => @as(u5, @as(u4, @intCast(n.format.element.index))) << 1 | @as(u5, 0b1) << 0,
15664 .half => @as(u5, @as(u3, @intCast(n.format.element.index))) << 2 | @as(u5, 0b10) << 0,
15665 .single => @as(u5, @as(u2, @intCast(n.format.element.index))) << 3 | @as(u5, 0b100) << 0,
15666 },
15667 .Q = sf,
15668 },
15669 } } };
15670 }
15671 /// C6.2.287 SMSUBL
15672 pub fn smsubl(d: Register, n: Register, m: Register, a: Register) Instruction {
15673 assert(d.format.general == .doubleword and n.format.general == .word and m.format.general == .word and a.format.general == .doubleword);
15674 return .{ .data_processing_register = .{ .data_processing_three_source = .{
15675 .smsubl = .{
15676 .Rd = d.alias.encode(.{}),
15677 .Rn = n.alias.encode(.{}),
15678 .Ra = a.alias.encode(.{}),
15679 .Rm = m.alias.encode(.{}),
15680 },
15681 } } };
15682 }
15683 /// C6.2.288 SMULH
15684 pub fn smulh(d: Register, n: Register, m: Register) Instruction {
15685 assert(d.format.general == .doubleword and n.format.general == .doubleword and m.format.general == .doubleword);
15686 return .{ .data_processing_register = .{ .data_processing_three_source = .{
15687 .smulh = .{
15688 .Rd = d.alias.encode(.{}),
15689 .Rn = n.alias.encode(.{}),
15690 .Rm = m.alias.encode(.{}),
15691 },
15692 } } };
15693 }
15694 /// C7.2.282 SQABS
15695 pub fn sqabs(d: Register, n: Register) Instruction {
15696 switch (d.format) {
15697 else => unreachable,
15698 .scalar => |elem_size| {
15699 assert(elem_size == n.format.scalar);
15700 return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
15701 .sqabs = .{
15702 .Rd = d.alias.encode(.{ .V = true }),
15703 .Rn = n.alias.encode(.{ .V = true }),
15704 .size = .fromScalarSize(elem_size),
15705 },
15706 } } };
15707 },
15708 .vector => |arrangement| {
15709 assert(arrangement != .@"1d" and n.format.vector == arrangement);
15710 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
15711 .sqabs = .{
15712 .Rd = d.alias.encode(.{ .V = true }),
15713 .Rn = n.alias.encode(.{ .V = true }),
15714 .size = arrangement.elemSize(),
15715 .Q = arrangement.size(),
15716 },
15717 } } };
15718 },
15719 }
15720 }
15721 /// C7.2.308 SQXTN
15722 pub fn sqxtn(d: Register, n: Register) Instruction {
15723 switch (d.format) {
15724 else => unreachable,
15725 .scalar => |elem_size| {
15726 assert(elem_size == n.format.scalar.n());
15727 return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
15728 .sqxtn = .{
15729 .Rd = d.alias.encode(.{ .V = true }),
15730 .Rn = n.alias.encode(.{ .V = true }),
15731 .size = .fromScalarSize(elem_size),
15732 },
15733 } } };
15734 },
15735 .vector => |arrangement| {
15736 assert(arrangement.len() == n.format.vector.len() and arrangement.elemSize() == n.format.vector.elemSize().n());
15737 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
15738 .sqxtn = .{
15739 .Rd = d.alias.encode(.{ .V = true }),
15740 .Rn = n.alias.encode(.{ .V = true }),
15741 .size = arrangement.elemSize(),
15742 .Q = arrangement.size(),
15743 },
15744 } } };
15745 },
15746 }
15747 }
15748 /// C7.2.308 SQXTN2
15749 pub fn sqxtn2(d: Register, n: Register) Instruction {
15750 const arrangement = d.format.vector;
15751 assert(arrangement.len() == n.format.vector.len() * 2 and arrangement.elemSize() == n.format.vector.elemSize().n());
15752 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
15753 .sqxtn = .{
15754 .Rd = d.alias.encode(.{ .V = true }),
15755 .Rn = n.alias.encode(.{ .V = true }),
15756 .size = arrangement.elemSize(),
15757 .Q = arrangement.size(),
15758 },
15759 } } };
15760 }
15761 /// C6.2.321 STP
15762 /// C7.2.330 STP (SIMD&FP)
15763 pub fn stp(t1: Register, t2: Register, form: union(enum) {
15764 post_index: struct { base: Register, index: i10 },
15765 pre_index: struct { base: Register, index: i10 },
15766 signed_offset: struct { base: Register, offset: i10 = 0 },
15767 base: Register,
15768 }) Instruction {
15769 switch (t1.format) {
15770 else => unreachable,
15771 .general => |sf| {
15772 assert(t2.format.general == sf);
15773 form: switch (form) {
15774 .post_index => |post_index| {
15775 assert(post_index.base.format.general == .doubleword);
15776 return .{ .load_store = .{ .register_pair_post_indexed = .{ .integer = .{
15777 .stp = .{
15778 .Rt = t1.alias.encode(.{}),
15779 .Rn = post_index.base.alias.encode(.{ .sp = true }),
15780 .Rt2 = t2.alias.encode(.{}),
15781 .imm7 = @intCast(@shrExact(post_index.index, @as(u2, 2) + @intFromEnum(sf))),
15782 .sf = sf,
15783 },
15784 } } } };
15785 },
15786 .pre_index => |pre_index| {
15787 assert(pre_index.base.format.general == .doubleword);
15788 return .{ .load_store = .{ .register_pair_pre_indexed = .{ .integer = .{
15789 .stp = .{
15790 .Rt = t1.alias.encode(.{}),
15791 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
15792 .Rt2 = t2.alias.encode(.{}),
15793 .imm7 = @intCast(@shrExact(pre_index.index, @as(u2, 2) + @intFromEnum(sf))),
15794 .sf = sf,
15795 },
15796 } } } };
15797 },
15798 .signed_offset => |signed_offset| {
15799 assert(signed_offset.base.format.general == .doubleword);
15800 return .{ .load_store = .{ .register_pair_offset = .{ .integer = .{
15801 .stp = .{
15802 .Rt = t1.alias.encode(.{}),
15803 .Rn = signed_offset.base.alias.encode(.{ .sp = true }),
15804 .Rt2 = t2.alias.encode(.{}),
15805 .imm7 = @intCast(@shrExact(signed_offset.offset, @as(u2, 2) + @intFromEnum(sf))),
15806 .sf = sf,
15807 },
15808 } } } };
15809 },
15810 .base => |base| continue :form .{ .signed_offset = .{ .base = base } },
15811 }
15812 },
15813 .scalar => |vs| {
15814 assert(t2.format.scalar == vs);
15815 form: switch (form) {
15816 .post_index => |post_index| {
15817 assert(post_index.base.format.general == .doubleword);
15818 return .{ .load_store = .{ .register_pair_post_indexed = .{ .vector = .{
15819 .stp = .{
15820 .Rt = t1.alias.encode(.{ .V = true }),
15821 .Rn = post_index.base.alias.encode(.{ .sp = true }),
15822 .Rt2 = t2.alias.encode(.{ .V = true }),
15823 .imm7 = @intCast(@shrExact(post_index.index, @intFromEnum(vs))),
15824 .opc = .encode(vs),
15825 },
15826 } } } };
15827 },
15828 .signed_offset => |signed_offset| {
15829 assert(signed_offset.base.format.general == .doubleword);
15830 return .{ .load_store = .{ .register_pair_offset = .{ .vector = .{
15831 .stp = .{
15832 .Rt = t1.alias.encode(.{ .V = true }),
15833 .Rn = signed_offset.base.alias.encode(.{ .sp = true }),
15834 .Rt2 = t2.alias.encode(.{ .V = true }),
15835 .imm7 = @intCast(@shrExact(signed_offset.offset, @intFromEnum(vs))),
15836 .opc = .encode(vs),
15837 },
15838 } } } };
15839 },
15840 .pre_index => |pre_index| {
15841 assert(pre_index.base.format.general == .doubleword);
15842 return .{ .load_store = .{ .register_pair_pre_indexed = .{ .vector = .{
15843 .stp = .{
15844 .Rt = t1.alias.encode(.{ .V = true }),
15845 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
15846 .Rt2 = t2.alias.encode(.{ .V = true }),
15847 .imm7 = @intCast(@shrExact(pre_index.index, @intFromEnum(vs))),
15848 .opc = .encode(vs),
15849 },
15850 } } } };
15851 },
15852 .base => |base| continue :form .{ .signed_offset = .{ .base = base } },
15853 }
15854 },
15855 }
15856 }
15857 /// C6.2.322 STR (immediate)
15858 /// C7.2.331 STR (immediate, SIMD&FP)
15859 pub fn str(t: Register, form: union(enum) {
15860 post_index: struct { base: Register, index: i9 },
15861 pre_index: struct { base: Register, index: i9 },
15862 unsigned_offset: struct { base: Register, offset: u16 = 0 },
15863 base: Register,
15864 }) Instruction {
15865 switch (t.format) {
15866 else => unreachable,
15867 .general => |sf| form: switch (form) {
15868 .post_index => |post_index| {
15869 assert(post_index.base.format.general == .doubleword);
15870 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
15871 .str = .{
15872 .Rt = t.alias.encode(.{}),
15873 .Rn = post_index.base.alias.encode(.{ .sp = true }),
15874 .imm9 = post_index.index,
15875 .sf = sf,
15876 },
15877 } } } };
15878 },
15879 .pre_index => |pre_index| {
15880 assert(pre_index.base.format.general == .doubleword);
15881 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
15882 .str = .{
15883 .Rt = t.alias.encode(.{}),
15884 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
15885 .imm9 = pre_index.index,
15886 .sf = sf,
15887 },
15888 } } } };
15889 },
15890 .unsigned_offset => |unsigned_offset| {
15891 assert(unsigned_offset.base.format.general == .doubleword);
15892 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
15893 .str = .{
15894 .Rt = t.alias.encode(.{}),
15895 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
15896 .imm12 = @intCast(@shrExact(unsigned_offset.offset, @as(u2, 2) + @intFromEnum(sf))),
15897 .sf = sf,
15898 },
15899 } } } };
15900 },
15901 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
15902 },
15903 .scalar => |vs| form: switch (form) {
15904 .post_index => |post_index| {
15905 assert(post_index.base.format.general == .doubleword);
15906 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .vector = .{
15907 .str = .{
15908 .Rt = t.alias.encode(.{ .V = true }),
15909 .Rn = post_index.base.alias.encode(.{ .sp = true }),
15910 .imm9 = post_index.index,
15911 .opc1 = .encode(vs),
15912 .size = .encode(vs),
15913 },
15914 } } } };
15915 },
15916 .pre_index => |pre_index| {
15917 assert(pre_index.base.format.general == .doubleword);
15918 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .vector = .{
15919 .str = .{
15920 .Rt = t.alias.encode(.{ .V = true }),
15921 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
15922 .imm9 = pre_index.index,
15923 .opc1 = .encode(vs),
15924 .size = .encode(vs),
15925 },
15926 } } } };
15927 },
15928 .unsigned_offset => |unsigned_offset| {
15929 assert(unsigned_offset.base.format.general == .doubleword);
15930 return .{ .load_store = .{ .register_unsigned_immediate = .{ .vector = .{
15931 .str = .{
15932 .Rt = t.alias.encode(.{ .V = true }),
15933 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
15934 .imm12 = @intCast(@shrExact(unsigned_offset.offset, @intFromEnum(vs))),
15935 .opc1 = .encode(vs),
15936 .size = .encode(vs),
15937 },
15938 } } } };
15939 },
15940 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
15941 },
15942 }
15943 }
15944 /// C6.2.324 STRB (immediate)
15945 pub fn strb(t: Register, form: union(enum) {
15946 post_index: struct { base: Register, index: i9 },
15947 pre_index: struct { base: Register, index: i9 },
15948 unsigned_offset: struct { base: Register, offset: u12 = 0 },
15949 base: Register,
15950 }) Instruction {
15951 assert(t.format.general == .word);
15952 form: switch (form) {
15953 .post_index => |post_index| {
15954 assert(post_index.base.format.general == .doubleword);
15955 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
15956 .strb = .{
15957 .Rt = t.alias.encode(.{}),
15958 .Rn = post_index.base.alias.encode(.{ .sp = true }),
15959 .imm9 = post_index.index,
15960 },
15961 } } } };
15962 },
15963 .pre_index => |pre_index| {
15964 assert(pre_index.base.format.general == .doubleword);
15965 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
15966 .strb = .{
15967 .Rt = t.alias.encode(.{}),
15968 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
15969 .imm9 = pre_index.index,
15970 },
15971 } } } };
15972 },
15973 .unsigned_offset => |unsigned_offset| {
15974 assert(unsigned_offset.base.format.general == .doubleword);
15975 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
15976 .strb = .{
15977 .Rt = t.alias.encode(.{}),
15978 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
15979 .imm12 = unsigned_offset.offset,
15980 },
15981 } } } };
15982 },
15983 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
15984 }
15985 }
15986 /// C6.2.326 STRH (immediate)
15987 pub fn strh(t: Register, form: union(enum) {
15988 post_index: struct { base: Register, index: i9 },
15989 pre_index: struct { base: Register, index: i9 },
15990 unsigned_offset: struct { base: Register, offset: u13 = 0 },
15991 base: Register,
15992 }) Instruction {
15993 assert(t.format.general == .word);
15994 form: switch (form) {
15995 .post_index => |post_index| {
15996 assert(post_index.base.format.general == .doubleword);
15997 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
15998 .strh = .{
15999 .Rt = t.alias.encode(.{}),
16000 .Rn = post_index.base.alias.encode(.{ .sp = true }),
16001 .imm9 = post_index.index,
16002 },
16003 } } } };
16004 },
16005 .pre_index => |pre_index| {
16006 assert(pre_index.base.format.general == .doubleword);
16007 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
16008 .strh = .{
16009 .Rt = t.alias.encode(.{}),
16010 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
16011 .imm9 = pre_index.index,
16012 },
16013 } } } };
16014 },
16015 .unsigned_offset => |unsigned_offset| {
16016 assert(unsigned_offset.base.format.general == .doubleword);
16017 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
16018 .strh = .{
16019 .Rt = t.alias.encode(.{}),
16020 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
16021 .imm12 = @intCast(@shrExact(unsigned_offset.offset, 1)),
16022 },
16023 } } } };
16024 },
16025 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
16026 }
16027 }
16028 /// C6.2.346 STUR
16029 /// C7.2.333 STUR (SIMD&FP)
16030 pub fn stur(t: Register, n: Register, simm: i9) Instruction {
16031 assert(n.format.general == .doubleword);
16032 switch (t.format) {
16033 else => unreachable,
16034 .general => |sf| return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
16035 .stur = .{
16036 .Rt = t.alias.encode(.{}),
16037 .Rn = n.alias.encode(.{ .sp = true }),
16038 .imm9 = simm,
16039 .sf = sf,
16040 },
16041 } } } },
16042 .scalar => |vs| return .{ .load_store = .{ .register_unscaled_immediate = .{ .vector = .{
16043 .stur = .{
16044 .Rt = t.alias.encode(.{ .V = true }),
16045 .Rn = n.alias.encode(.{ .sp = true }),
16046 .imm9 = simm,
16047 .opc1 = .encode(vs),
16048 .size = .encode(vs),
16049 },
16050 } } } },
16051 }
16052 }
16053 /// C6.2.347 STURB
16054 pub fn sturb(t: Register, n: Register, simm: i9) Instruction {
16055 assert(t.format.general == .word and n.format.general == .doubleword);
16056 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
16057 .sturb = .{
16058 .Rt = t.alias.encode(.{}),
16059 .Rn = n.alias.encode(.{ .sp = true }),
16060 .imm9 = simm,
16061 },
16062 } } } };
16063 }
16064 /// C6.2.348 STURH
16065 pub fn sturh(t: Register, n: Register, simm: i9) Instruction {
16066 assert(t.format.general == .word and n.format.general == .doubleword);
16067 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
16068 .sturh = .{
16069 .Rt = t.alias.encode(.{}),
16070 .Rn = n.alias.encode(.{ .sp = true }),
16071 .imm9 = simm,
16072 },
16073 } } } };
16074 }
16075 /// C6.2.356 SUB (extended register)
16076 /// C6.2.357 SUB (immediate)
16077 /// C6.2.358 SUB (shifted register)
16078 pub fn sub(d: Register, n: Register, form: union(enum) {
16079 extended_register_explicit: struct {
16080 register: Register,
16081 option: DataProcessingRegister.AddSubtractExtendedRegister.Option,
16082 amount: DataProcessingRegister.AddSubtractExtendedRegister.Extend.Amount,
16083 },
16084 extended_register: struct { register: Register, extend: DataProcessingRegister.AddSubtractExtendedRegister.Extend },
16085 immediate: u12,
16086 shifted_immediate: struct { immediate: u12, lsl: DataProcessingImmediate.AddSubtractImmediate.Shift = .@"0" },
16087 register: Register,
16088 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
16089 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
16090 }) Instruction {
16091 const sf = d.format.general;
16092 assert(n.format.general == sf);
16093 form: switch (form) {
16094 .extended_register_explicit => |extended_register_explicit| {
16095 assert(extended_register_explicit.register.format.general == switch (sf) {
16096 .word => .word,
16097 .doubleword => extended_register_explicit.option.sf(),
16098 });
16099 return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
16100 .sub = .{
16101 .Rd = d.alias.encode(.{ .sp = true }),
16102 .Rn = n.alias.encode(.{ .sp = true }),
16103 .imm3 = switch (extended_register_explicit.amount) {
16104 0...4 => |amount| amount,
16105 else => unreachable,
16106 },
16107 .option = extended_register_explicit.option,
16108 .Rm = extended_register_explicit.register.alias.encode(.{}),
16109 .sf = sf,
16110 },
16111 } } };
16112 },
16113 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
16114 .register = extended_register.register,
16115 .option = extended_register.extend,
16116 .amount = switch (extended_register.extend) {
16117 .uxtb, .uxth, .uxtw, .uxtx, .sxtb, .sxth, .sxtw, .sxtx => |amount| amount,
16118 },
16119 } },
16120 .immediate => |immediate| continue :form .{ .shifted_immediate = .{ .immediate = immediate } },
16121 .shifted_immediate => |shifted_immediate| {
16122 return .{ .data_processing_immediate = .{ .add_subtract_immediate = .{
16123 .sub = .{
16124 .Rd = d.alias.encode(.{ .sp = true }),
16125 .Rn = n.alias.encode(.{ .sp = true }),
16126 .imm12 = shifted_immediate.immediate,
16127 .sh = shifted_immediate.lsl,
16128 .sf = sf,
16129 },
16130 } } };
16131 },
16132 .register => |register| continue :form if (d.alias == .sp or n.alias == .sp or register.alias == .sp)
16133 .{ .extended_register = .{ .register = register, .extend = switch (sf) {
16134 .word => .{ .uxtw = 0 },
16135 .doubleword => .{ .uxtx = 0 },
16136 } } }
16137 else
16138 .{ .shifted_register = .{ .register = register } },
16139 .shifted_register_explicit => |shifted_register_explicit| {
16140 assert(shifted_register_explicit.register.format.general == sf);
16141 return .{ .data_processing_register = .{ .add_subtract_shifted_register = .{
16142 .sub = .{
16143 .Rd = d.alias.encode(.{}),
16144 .Rn = n.alias.encode(.{}),
16145 .imm6 = switch (sf) {
16146 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
16147 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
16148 },
16149 .Rm = shifted_register_explicit.register.alias.encode(.{}),
16150 .shift = switch (shifted_register_explicit.shift) {
16151 .lsl, .lsr, .asr => |shift| shift,
16152 .ror => unreachable,
16153 },
16154 .sf = sf,
16155 },
16156 } } };
16157 },
16158 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
16159 .register = shifted_register.register,
16160 .shift = shifted_register.shift,
16161 .amount = switch (shifted_register.shift) {
16162 .lsl, .lsr, .asr => |amount| amount,
16163 .ror => unreachable,
16164 },
16165 } },
16166 }
16167 }
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 }
16180 /// C6.2.362 SUBS (extended register)
16181 /// C6.2.363 SUBS (immediate)
16182 /// C6.2.364 SUBS (shifted register)
16183 pub fn subs(d: Register, n: Register, form: union(enum) {
16184 extended_register_explicit: struct {
16185 register: Register,
16186 option: DataProcessingRegister.AddSubtractExtendedRegister.Option,
16187 amount: DataProcessingRegister.AddSubtractExtendedRegister.Extend.Amount,
16188 },
16189 extended_register: struct { register: Register, extend: DataProcessingRegister.AddSubtractExtendedRegister.Extend },
16190 immediate: u12,
16191 shifted_immediate: struct { immediate: u12, lsl: DataProcessingImmediate.AddSubtractImmediate.Shift = .@"0" },
16192 register: Register,
16193 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
16194 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
16195 }) Instruction {
16196 const sf = d.format.general;
16197 assert(n.format.general == sf);
16198 form: switch (form) {
16199 .extended_register_explicit => |extended_register_explicit| {
16200 assert(extended_register_explicit.register.format.general == switch (sf) {
16201 .word => .word,
16202 .doubleword => extended_register_explicit.option.sf(),
16203 });
16204 return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
16205 .subs = .{
16206 .Rd = d.alias.encode(.{}),
16207 .Rn = n.alias.encode(.{ .sp = true }),
16208 .imm3 = switch (extended_register_explicit.amount) {
16209 0...4 => |amount| amount,
16210 else => unreachable,
16211 },
16212 .option = extended_register_explicit.option,
16213 .Rm = extended_register_explicit.register.alias.encode(.{}),
16214 .sf = sf,
16215 },
16216 } } };
16217 },
16218 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
16219 .register = extended_register.register,
16220 .option = extended_register.extend,
16221 .amount = switch (extended_register.extend) {
16222 .uxtb, .uxth, .uxtw, .uxtx, .sxtb, .sxth, .sxtw, .sxtx => |amount| amount,
16223 },
16224 } },
16225 .immediate => |immediate| continue :form .{ .shifted_immediate = .{ .immediate = immediate } },
16226 .shifted_immediate => |shifted_immediate| {
16227 return .{ .data_processing_immediate = .{ .add_subtract_immediate = .{
16228 .subs = .{
16229 .Rd = d.alias.encode(.{}),
16230 .Rn = n.alias.encode(.{ .sp = true }),
16231 .imm12 = shifted_immediate.immediate,
16232 .sh = shifted_immediate.lsl,
16233 .sf = sf,
16234 },
16235 } } };
16236 },
16237 .register => |register| continue :form if (d.alias == .sp or n.alias == .sp or register.alias == .sp)
16238 .{ .extended_register = .{ .register = register, .extend = switch (sf) {
16239 .word => .{ .uxtw = 0 },
16240 .doubleword => .{ .uxtx = 0 },
16241 } } }
16242 else
16243 .{ .shifted_register = .{ .register = register } },
16244 .shifted_register_explicit => |shifted_register_explicit| {
16245 assert(shifted_register_explicit.register.format.general == sf);
16246 return .{ .data_processing_register = .{ .add_subtract_shifted_register = .{
16247 .subs = .{
16248 .Rd = d.alias.encode(.{}),
16249 .Rn = n.alias.encode(.{}),
16250 .imm6 = switch (sf) {
16251 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
16252 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
16253 },
16254 .Rm = shifted_register_explicit.register.alias.encode(.{}),
16255 .shift = switch (shifted_register_explicit.shift) {
16256 .lsl, .lsr, .asr => |shift| shift,
16257 .ror => unreachable,
16258 },
16259 .sf = sf,
16260 },
16261 } } };
16262 },
16263 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
16264 .register = shifted_register.register,
16265 .shift = shifted_register.shift,
16266 .amount = switch (shifted_register.shift) {
16267 .lsl, .lsr, .asr => |amount| amount,
16268 .ror => unreachable,
16269 },
16270 } },
16271 }
16272 }
16273 /// C7.2.337 SUQADD
16274 pub fn suqadd(d: Register, n: Register) Instruction {
16275 switch (d.format) {
16276 else => unreachable,
16277 .scalar => |elem_size| {
16278 assert(elem_size == n.format.scalar);
16279 return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
16280 .suqadd = .{
16281 .Rd = d.alias.encode(.{ .V = true }),
16282 .Rn = n.alias.encode(.{ .V = true }),
16283 .size = .fromScalarSize(elem_size),
16284 },
16285 } } };
16286 },
16287 .vector => |arrangement| {
16288 assert(arrangement != .@"1d" and n.format.vector == arrangement);
16289 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
16290 .suqadd = .{
16291 .Rd = d.alias.encode(.{ .V = true }),
16292 .Rn = n.alias.encode(.{ .V = true }),
16293 .size = arrangement.elemSize(),
16294 .Q = arrangement.size(),
16295 },
16296 } } };
16297 },
16298 }
16299 }
16300 /// C6.2.365 SVC
16301 pub fn svc(imm: u16) Instruction {
16302 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
16303 .svc = .{ .imm16 = imm },
16304 } } };
16305 }
16306 /// C6.2.372 SYS
16307 pub fn sys(op1: u3, n: u4, m: u4, op2: u3, t: Register) Instruction {
16308 assert(t.format.general == .doubleword);
16309 return .{ .branch_exception_generating_system = .{ .system = .{
16310 .sys = .{
16311 .Rt = t.alias.encode(.{}),
16312 .op2 = op2,
16313 .CRm = m,
16314 .CRn = n,
16315 .op1 = op1,
16316 },
16317 } } };
16318 }
16319 /// C6.2.373 SYSL
16320 pub fn sysl(t: Register, op1: u3, n: u4, m: u4, op2: u3) Instruction {
16321 assert(t.format.general == .doubleword);
16322 return .{ .branch_exception_generating_system = .{ .system = .{
16323 .sysl = .{
16324 .Rt = t.alias.encode(.{}),
16325 .op2 = op2,
16326 .CRm = m,
16327 .CRn = n,
16328 .op1 = op1,
16329 },
16330 } } };
16331 }
16332 /// C6.2.374 TBNZ
16333 pub fn tbnz(t: Register, imm: u6, label: i16) Instruction {
16334 return .{ .branch_exception_generating_system = .{ .test_branch_immediate = .{
16335 .tbnz = .{
16336 .Rt = t.alias.encode(.{}),
16337 .imm14 = @intCast(@shrExact(label, 2)),
16338 .b40 = @truncate(switch (t.format.general) {
16339 .word => @as(u5, @intCast(imm)),
16340 .doubleword => imm,
16341 }),
16342 .b5 = @intCast(imm >> 5),
16343 },
16344 } } };
16345 }
16346 /// C6.2.375 TBZ
16347 pub fn tbz(t: Register, imm: u6, label: i16) Instruction {
16348 return .{ .branch_exception_generating_system = .{ .test_branch_immediate = .{
16349 .tbz = .{
16350 .Rt = t.alias.encode(.{}),
16351 .imm14 = @intCast(@shrExact(label, 2)),
16352 .b40 = @truncate(switch (t.format.general) {
16353 .word => @as(u5, @intCast(imm)),
16354 .doubleword => imm,
16355 }),
16356 .b5 = @intCast(imm >> 5),
16357 },
16358 } } };
16359 }
16360 /// C6.2.376 TCANCEL
16361 pub fn tcancel(imm: u16) Instruction {
16362 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
16363 .tcancel = .{ .imm16 = imm },
16364 } } };
16365 }
16366 /// C6.2.385 UBFM
16367 pub fn ubfm(d: Register, n: Register, bitmask: DataProcessingImmediate.Bitmask) Instruction {
16368 const sf = d.format.general;
16369 assert(n.format.general == sf and bitmask.validBitfield(sf));
16370 return .{ .data_processing_immediate = .{ .bitfield = .{
16371 .ubfm = .{
16372 .Rd = d.alias.encode(.{}),
16373 .Rn = n.alias.encode(.{}),
16374 .imm = bitmask,
16375 .sf = sf,
16376 },
16377 } } };
16378 }
16379 /// C7.2.353 UCVTF (vector, integer)
16380 /// C7.2.355 UCVTF (scalar, integer)
16381 pub fn ucvtf(d: Register, n: Register) Instruction {
16382 switch (d.format) {
16383 else => unreachable,
16384 .scalar => |ftype| switch (n.format) {
16385 else => unreachable,
16386 .scalar => |elem_size| {
16387 assert(ftype == elem_size);
16388 switch (ftype) {
16389 else => unreachable,
16390 .half => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous_fp16 = .{
16391 .ucvtf = .{
16392 .Rd = d.alias.encode(.{ .V = true }),
16393 .Rn = n.alias.encode(.{ .V = true }),
16394 },
16395 } } },
16396 .single, .double => return .{ .data_processing_vector = .{ .simd_scalar_two_register_miscellaneous = .{
16397 .ucvtf = .{
16398 .Rd = d.alias.encode(.{ .V = true }),
16399 .Rn = n.alias.encode(.{ .V = true }),
16400 .sz = .fromScalarSize(ftype),
16401 },
16402 } } },
16403 }
16404 },
16405 .general => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
16406 .ucvtf = .{
16407 .Rd = d.alias.encode(.{ .V = true }),
16408 .Rn = n.alias.encode(.{}),
16409 .ftype = .fromScalarSize(ftype),
16410 .sf = sf,
16411 },
16412 } } },
16413 },
16414 .vector => |arrangement| {
16415 assert(arrangement != .@"1d" and n.format.vector == arrangement);
16416 switch (arrangement.elemSize()) {
16417 else => unreachable,
16418 .half => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous_fp16 = .{
16419 .ucvtf = .{
16420 .Rd = d.alias.encode(.{ .V = true }),
16421 .Rn = n.alias.encode(.{ .V = true }),
16422 .Q = arrangement.size(),
16423 },
16424 } } },
16425 .single, .double => return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
16426 .ucvtf = .{
16427 .Rd = d.alias.encode(.{ .V = true }),
16428 .Rn = n.alias.encode(.{ .V = true }),
16429 .sz = arrangement.elemSz(),
16430 .Q = arrangement.size(),
16431 },
16432 } } },
16433 }
16434 },
16435 }
16436 }
16437 /// C6.2.387 UDF
16438 pub fn udf(imm: u16) Instruction {
16439 return .{ .reserved = .{
16440 .udf = .{ .imm16 = imm },
16441 } };
16442 }
16443 /// C6.2.388 UDIV
16444 pub fn udiv(d: Register, n: Register, m: Register) Instruction {
16445 const sf = d.format.general;
16446 assert(n.format.general == sf and m.format.general == sf);
16447 return .{ .data_processing_register = .{ .data_processing_two_source = .{
16448 .udiv = .{
16449 .Rd = d.alias.encode(.{}),
16450 .Rn = n.alias.encode(.{}),
16451 .Rm = m.alias.encode(.{}),
16452 .sf = sf,
16453 },
16454 } } };
16455 }
16456 /// C6.2.389 UMADDL
16457 pub fn umaddl(d: Register, n: Register, m: Register, a: Register) Instruction {
16458 assert(d.format.general == .doubleword and n.format.general == .word and m.format.general == .word and a.format.general == .doubleword);
16459 return .{ .data_processing_register = .{ .data_processing_three_source = .{
16460 .umaddl = .{
16461 .Rd = d.alias.encode(.{}),
16462 .Rn = n.alias.encode(.{}),
16463 .Ra = a.alias.encode(.{}),
16464 .Rm = m.alias.encode(.{}),
16465 },
16466 } } };
16467 }
16468 /// C6.2.391 UMSUBL
16469 pub fn umsubl(d: Register, n: Register, m: Register, a: Register) Instruction {
16470 assert(d.format.general == .doubleword and n.format.general == .word and m.format.general == .word and a.format.general == .doubleword);
16471 return .{ .data_processing_register = .{ .data_processing_three_source = .{
16472 .umsubl = .{
16473 .Rd = d.alias.encode(.{}),
16474 .Rn = n.alias.encode(.{}),
16475 .Ra = a.alias.encode(.{}),
16476 .Rm = m.alias.encode(.{}),
16477 },
16478 } } };
16479 }
16480 /// C7.2.371 UMOV
16481 pub fn umov(d: Register, n: Register) Instruction {
16482 const sf = d.format.general;
16483 const vs = n.format.element.size;
16484 switch (vs) {
16485 else => unreachable,
16486 .byte, .half, .single => assert(sf == .word),
16487 .double => assert(sf == .doubleword),
16488 }
16489 return .{ .data_processing_vector = .{ .simd_copy = .{
16490 .umov = .{
16491 .Rd = d.alias.encode(.{}),
16492 .Rn = n.alias.encode(.{ .V = true }),
16493 .imm5 = switch (vs) {
16494 else => unreachable,
16495 .byte => @as(u5, @as(u4, @intCast(n.format.element.index))) << 1 | @as(u5, 0b1) << 0,
16496 .half => @as(u5, @as(u3, @intCast(n.format.element.index))) << 2 | @as(u5, 0b10) << 0,
16497 .single => @as(u5, @as(u2, @intCast(n.format.element.index))) << 3 | @as(u5, 0b100) << 0,
16498 .double => @as(u5, @as(u1, @intCast(n.format.element.index))) << 4 | @as(u5, 0b1000) << 0,
16499 },
16500 .Q = sf,
16501 },
16502 } } };
16503 }
16504 /// C6.2.392 UMULH
16505 pub fn umulh(d: Register, n: Register, m: Register) Instruction {
16506 assert(d.format.general == .doubleword and n.format.general == .doubleword and m.format.general == .doubleword);
16507 return .{ .data_processing_register = .{ .data_processing_three_source = .{
16508 .umulh = .{
16509 .Rd = d.alias.encode(.{}),
16510 .Rn = n.alias.encode(.{}),
16511 .Rm = m.alias.encode(.{}),
16512 },
16513 } } };
16514 }
16515 /// C6.2.396 WFE
16516 pub fn wfe() Instruction {
16517 return .{ .branch_exception_generating_system = .{ .hints = .{
16518 .wfe = .{},
16519 } } };
16520 }
16521 /// C6.2.398 WFI
16522 pub fn wfi() Instruction {
16523 return .{ .branch_exception_generating_system = .{ .hints = .{
16524 .wfi = .{},
16525 } } };
16526 }
16527 /// C6.2.400 XAFLAG
16528 pub fn xaflag() Instruction {
16529 return .{ .branch_exception_generating_system = .{ .pstate = .{
16530 .xaflag = .{},
16531 } } };
16532 }
16533 /// C6.2.402 YIELD
16534 pub fn yield() Instruction {
16535 return .{ .branch_exception_generating_system = .{ .hints = .{
16536 .yield = .{},
16537 } } };
16538 }
16539
16540 pub const size = @divExact(@bitSizeOf(Backing), 8);
16541 pub const Backing = u32;
16542 pub fn read(mem: *const [size]u8) Instruction {
16543 return @bitCast(std.mem.readInt(Backing, mem, .little));
16544 }
16545 pub fn write(inst: Instruction, mem: *[size]u8) void {
16546 std.mem.writeInt(Backing, mem, @bitCast(inst), .little);
16547 }
16548
16549 pub fn format(inst: Instruction, writer: *std.Io.Writer) std.Io.Writer.Error!void {
16550 const dis: aarch64.Disassemble = .{};
16551 try dis.printInstruction(inst, writer);
16552 }
16553
16554 comptime {
16555 @setEvalBranchQuota(110_000);
16556 verify(@typeName(Instruction), Instruction);
16557 }
16558 fn verify(name: []const u8, Type: type) void {
16559 switch (@typeInfo(Type)) {
16560 .@"union" => |info| {
16561 if (info.layout != .@"packed" or @bitSizeOf(Type) != @bitSizeOf(Backing)) {
16562 @compileLog(name ++ " should have u32 abi");
16563 }
16564 for (info.fields) |field| verify(name ++ "." ++ field.name, field.type);
16565 },
16566 .@"struct" => |info| {
16567 if (info.layout != .@"packed" or info.backing_integer != Backing) {
16568 @compileLog(name ++ " should have u32 abi");
16569 }
16570 var bit_offset = 0;
16571 for (info.fields) |field| {
16572 if (std.mem.startsWith(u8, field.name, "encoded")) {
16573 if (if (std.fmt.parseInt(u5, field.name["encoded".len..], 10)) |encoded_bit_offset| encoded_bit_offset != bit_offset else |_| true) {
16574 @compileError(std.fmt.comptimePrint("{s}.{s} should be named encoded{d}", .{ name, field.name, bit_offset }));
16575 }
16576 if (field.default_value_ptr != null) {
16577 @compileError(std.fmt.comptimePrint("{s}.{s} should be named decoded{d}", .{ name, field.name, bit_offset }));
16578 }
16579 } else if (std.mem.startsWith(u8, field.name, "decoded")) {
16580 if (if (std.fmt.parseInt(u5, field.name["decoded".len..], 10)) |decoded_bit_offset| decoded_bit_offset != bit_offset else |_| true) {
16581 @compileError(std.fmt.comptimePrint("{s}.{s} should be named decoded{d}", .{ name, field.name, bit_offset }));
16582 }
16583 if (field.default_value_ptr == null) {
16584 @compileError(std.fmt.comptimePrint("{s}.{s} should be named encoded{d}", .{ name, field.name, bit_offset }));
16585 }
16586 }
16587 bit_offset += @bitSizeOf(field.type);
16588 }
16589 },
16590 else => @compileError(name ++ " has an unexpected field type"),
16591 }
16592 }
16593};
16594
16595const aarch64 = @import("../aarch64.zig");
16596const assert = std.debug.assert;
16597const std = @import("std");