1// Copyright 2017 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package arm64asm
6
7import (
8	"fmt"
9	"strings"
10)
11
12// An Op is an ARM64 opcode.
13type Op uint16
14
15// NOTE: The actual Op values are defined in tables.go.
16// They are chosen to simplify instruction decoding and
17// are not a dense packing from 0 to N, although the
18// density is high, probably at least 90%.
19
20func (op Op) String() string {
21	if op >= Op(len(opstr)) || opstr[op] == "" {
22		return fmt.Sprintf("Op(%d)", int(op))
23	}
24	return opstr[op]
25}
26
27// An Inst is a single instruction.
28type Inst struct {
29	Op   Op     // Opcode mnemonic
30	Enc  uint32 // Raw encoding bits.
31	Args Args   // Instruction arguments, in ARM manual order.
32}
33
34func (i Inst) String() string {
35	var args []string
36	for _, arg := range i.Args {
37		if arg == nil {
38			break
39		}
40		args = append(args, arg.String())
41	}
42	return i.Op.String() + " " + strings.Join(args, ", ")
43}
44
45// An Args holds the instruction arguments.
46// If an instruction has fewer than 5 arguments,
47// the final elements in the array are nil.
48type Args [5]Arg
49
50// An Arg is a single instruction argument, one of these types:
51// Reg, RegSP, ImmShift, RegExtshiftAmount, PCRel, MemImmediate,
52// MemExtend, Imm, Imm64, Imm_hint, Imm_clrex, Imm_dcps, Cond,
53// Imm_c, Imm_option, Imm_prfop, Pstatefield, Systemreg, Imm_fp
54// RegisterWithArrangement, RegisterWithArrangementAndIndex.
55type Arg interface {
56	isArg()
57	String() string
58}
59
60// A Reg is a single register.
61// The zero value denotes W0, not the absence of a register.
62type Reg uint16
63
64const (
65	W0 Reg = iota
66	W1
67	W2
68	W3
69	W4
70	W5
71	W6
72	W7
73	W8
74	W9
75	W10
76	W11
77	W12
78	W13
79	W14
80	W15
81	W16
82	W17
83	W18
84	W19
85	W20
86	W21
87	W22
88	W23
89	W24
90	W25
91	W26
92	W27
93	W28
94	W29
95	W30
96	WZR
97
98	X0
99	X1
100	X2
101	X3
102	X4
103	X5
104	X6
105	X7
106	X8
107	X9
108	X10
109	X11
110	X12
111	X13
112	X14
113	X15
114	X16
115	X17
116	X18
117	X19
118	X20
119	X21
120	X22
121	X23
122	X24
123	X25
124	X26
125	X27
126	X28
127	X29
128	X30
129	XZR
130
131	B0
132	B1
133	B2
134	B3
135	B4
136	B5
137	B6
138	B7
139	B8
140	B9
141	B10
142	B11
143	B12
144	B13
145	B14
146	B15
147	B16
148	B17
149	B18
150	B19
151	B20
152	B21
153	B22
154	B23
155	B24
156	B25
157	B26
158	B27
159	B28
160	B29
161	B30
162	B31
163
164	H0
165	H1
166	H2
167	H3
168	H4
169	H5
170	H6
171	H7
172	H8
173	H9
174	H10
175	H11
176	H12
177	H13
178	H14
179	H15
180	H16
181	H17
182	H18
183	H19
184	H20
185	H21
186	H22
187	H23
188	H24
189	H25
190	H26
191	H27
192	H28
193	H29
194	H30
195	H31
196
197	S0
198	S1
199	S2
200	S3
201	S4
202	S5
203	S6
204	S7
205	S8
206	S9
207	S10
208	S11
209	S12
210	S13
211	S14
212	S15
213	S16
214	S17
215	S18
216	S19
217	S20
218	S21
219	S22
220	S23
221	S24
222	S25
223	S26
224	S27
225	S28
226	S29
227	S30
228	S31
229
230	D0
231	D1
232	D2
233	D3
234	D4
235	D5
236	D6
237	D7
238	D8
239	D9
240	D10
241	D11
242	D12
243	D13
244	D14
245	D15
246	D16
247	D17
248	D18
249	D19
250	D20
251	D21
252	D22
253	D23
254	D24
255	D25
256	D26
257	D27
258	D28
259	D29
260	D30
261	D31
262
263	Q0
264	Q1
265	Q2
266	Q3
267	Q4
268	Q5
269	Q6
270	Q7
271	Q8
272	Q9
273	Q10
274	Q11
275	Q12
276	Q13
277	Q14
278	Q15
279	Q16
280	Q17
281	Q18
282	Q19
283	Q20
284	Q21
285	Q22
286	Q23
287	Q24
288	Q25
289	Q26
290	Q27
291	Q28
292	Q29
293	Q30
294	Q31
295
296	V0
297	V1
298	V2
299	V3
300	V4
301	V5
302	V6
303	V7
304	V8
305	V9
306	V10
307	V11
308	V12
309	V13
310	V14
311	V15
312	V16
313	V17
314	V18
315	V19
316	V20
317	V21
318	V22
319	V23
320	V24
321	V25
322	V26
323	V27
324	V28
325	V29
326	V30
327	V31
328
329	WSP = WZR // These are different registers with the same encoding.
330	SP  = XZR // These are different registers with the same encoding.
331)
332
333func (Reg) isArg() {}
334
335func (r Reg) String() string {
336	switch {
337	case r == WZR:
338		return "WZR"
339	case r == XZR:
340		return "XZR"
341	case W0 <= r && r <= W30:
342		return fmt.Sprintf("W%d", int(r-W0))
343	case X0 <= r && r <= X30:
344		return fmt.Sprintf("X%d", int(r-X0))
345
346	case B0 <= r && r <= B31:
347		return fmt.Sprintf("B%d", int(r-B0))
348	case H0 <= r && r <= H31:
349		return fmt.Sprintf("H%d", int(r-H0))
350	case S0 <= r && r <= S31:
351		return fmt.Sprintf("S%d", int(r-S0))
352	case D0 <= r && r <= D31:
353		return fmt.Sprintf("D%d", int(r-D0))
354	case Q0 <= r && r <= Q31:
355		return fmt.Sprintf("Q%d", int(r-Q0))
356
357	case V0 <= r && r <= V31:
358		return fmt.Sprintf("V%d", int(r-V0))
359	default:
360		return fmt.Sprintf("Reg(%d)", int(r))
361	}
362}
363
364// A RegSP represent a register and X31/W31 is regarded as SP/WSP.
365type RegSP Reg
366
367func (RegSP) isArg() {}
368
369func (r RegSP) String() string {
370	switch Reg(r) {
371	case WSP:
372		return "WSP"
373	case SP:
374		return "SP"
375	default:
376		return Reg(r).String()
377	}
378}
379
380type ImmShift struct {
381	imm   uint16
382	shift uint8
383}
384
385func (ImmShift) isArg() {}
386
387func (is ImmShift) String() string {
388	if is.shift == 0 {
389		return fmt.Sprintf("#%#x", is.imm)
390	}
391	if is.shift < 128 {
392		return fmt.Sprintf("#%#x, LSL #%d", is.imm, is.shift)
393	}
394	return fmt.Sprintf("#%#x, MSL #%d", is.imm, is.shift-128)
395}
396
397type ExtShift uint8
398
399const (
400	_ ExtShift = iota
401	uxtb
402	uxth
403	uxtw
404	uxtx
405	sxtb
406	sxth
407	sxtw
408	sxtx
409	lsl
410	lsr
411	asr
412	ror
413)
414
415func (extShift ExtShift) String() string {
416	switch extShift {
417	case uxtb:
418		return "UXTB"
419
420	case uxth:
421		return "UXTH"
422
423	case uxtw:
424		return "UXTW"
425
426	case uxtx:
427		return "UXTX"
428
429	case sxtb:
430		return "SXTB"
431
432	case sxth:
433		return "SXTH"
434
435	case sxtw:
436		return "SXTW"
437
438	case sxtx:
439		return "SXTX"
440
441	case lsl:
442		return "LSL"
443
444	case lsr:
445		return "LSR"
446
447	case asr:
448		return "ASR"
449
450	case ror:
451		return "ROR"
452	}
453	return ""
454}
455
456type RegExtshiftAmount struct {
457	reg       Reg
458	extShift  ExtShift
459	amount    uint8
460	show_zero bool
461}
462
463func (RegExtshiftAmount) isArg() {}
464
465func (rea RegExtshiftAmount) String() string {
466	buf := rea.reg.String()
467	if rea.extShift != ExtShift(0) {
468		buf += ", " + rea.extShift.String()
469		if rea.amount != 0 {
470			buf += fmt.Sprintf(" #%d", rea.amount)
471		} else {
472			if rea.show_zero == true {
473				buf += fmt.Sprintf(" #%d", rea.amount)
474			}
475		}
476	}
477	return buf
478}
479
480// A PCRel describes a memory address (usually a code label)
481// as a distance relative to the program counter.
482type PCRel int64
483
484func (PCRel) isArg() {}
485
486func (r PCRel) String() string {
487	return fmt.Sprintf(".%+#x", uint64(r))
488}
489
490// An AddrMode is an ARM addressing mode.
491type AddrMode uint8
492
493const (
494	_             AddrMode = iota
495	AddrPostIndex          // [R], X - use address R, set R = R + X
496	AddrPreIndex           // [R, X]! - use address R + X, set R = R + X
497	AddrOffset             // [R, X] - use address R + X
498	AddrPostReg            // [Rn], Rm - - use address Rn, set Rn = Rn + Rm
499)
500
501// A MemImmediate is a memory reference made up of a base R and immediate X.
502// The effective memory address is R or R+X depending on AddrMode.
503type MemImmediate struct {
504	Base RegSP
505	Mode AddrMode
506	imm  int32
507}
508
509func (MemImmediate) isArg() {}
510
511func (m MemImmediate) String() string {
512	R := m.Base.String()
513	X := fmt.Sprintf("#%d", m.imm)
514
515	switch m.Mode {
516	case AddrOffset:
517		if X == "#0" {
518			return fmt.Sprintf("[%s]", R)
519		}
520		return fmt.Sprintf("[%s,%s]", R, X)
521	case AddrPreIndex:
522		return fmt.Sprintf("[%s,%s]!", R, X)
523	case AddrPostIndex:
524		return fmt.Sprintf("[%s],%s", R, X)
525	case AddrPostReg:
526		post := Reg(X0) + Reg(m.imm)
527		postR := post.String()
528		return fmt.Sprintf("[%s], %s", R, postR)
529	}
530	return fmt.Sprintf("unimplemented!")
531}
532
533// A MemExtend is a memory reference made up of a base R and index expression X.
534// The effective memory address is R or R+X depending on Index, Extend and Amount.
535type MemExtend struct {
536	Base   RegSP
537	Index  Reg
538	Extend ExtShift
539	// Amount indicates the index shift amount (but also see ShiftMustBeZero field below).
540	Amount uint8
541	// Refer to ARM reference manual, for byte load/store(register), the index
542	// shift amount must be 0, encoded in "S" as 0 if omitted, or as 1 if present.
543	// a.ShiftMustBeZero is set true indicates the index shift amount must be 0.
544	// In GNU syntax, a #0 shift amount is printed if Amount is 1 but ShiftMustBeZero
545	// is true; #0 is not printed if Amount is 0 and ShiftMustBeZero is true.
546	// Both cases represent shift by 0 bit.
547	ShiftMustBeZero bool
548}
549
550func (MemExtend) isArg() {}
551
552func (m MemExtend) String() string {
553	Rbase := m.Base.String()
554	RIndex := m.Index.String()
555	if m.ShiftMustBeZero {
556		if m.Amount != 0 {
557			return fmt.Sprintf("[%s,%s,%s #0]", Rbase, RIndex, m.Extend.String())
558		} else {
559			if m.Extend != lsl {
560				return fmt.Sprintf("[%s,%s,%s]", Rbase, RIndex, m.Extend.String())
561			} else {
562				return fmt.Sprintf("[%s,%s]", Rbase, RIndex)
563			}
564		}
565	} else {
566		if m.Amount != 0 {
567			return fmt.Sprintf("[%s,%s,%s #%d]", Rbase, RIndex, m.Extend.String(), m.Amount)
568		} else {
569			if m.Extend != lsl {
570				return fmt.Sprintf("[%s,%s,%s]", Rbase, RIndex, m.Extend.String())
571			} else {
572				return fmt.Sprintf("[%s,%s]", Rbase, RIndex)
573			}
574		}
575	}
576}
577
578// An Imm is an integer constant.
579type Imm struct {
580	Imm     uint32
581	Decimal bool
582}
583
584func (Imm) isArg() {}
585
586func (i Imm) String() string {
587	if !i.Decimal {
588		return fmt.Sprintf("#%#x", i.Imm)
589	} else {
590		return fmt.Sprintf("#%d", i.Imm)
591	}
592}
593
594type Imm64 struct {
595	Imm     uint64
596	Decimal bool
597}
598
599func (Imm64) isArg() {}
600
601func (i Imm64) String() string {
602	if !i.Decimal {
603		return fmt.Sprintf("#%#x", i.Imm)
604	} else {
605		return fmt.Sprintf("#%d", i.Imm)
606	}
607}
608
609// An Imm_hint is an integer constant for HINT instruction.
610type Imm_hint uint8
611
612func (Imm_hint) isArg() {}
613
614func (i Imm_hint) String() string {
615	return fmt.Sprintf("#%#x", uint32(i))
616}
617
618// An Imm_clrex is an integer constant for CLREX instruction.
619type Imm_clrex uint8
620
621func (Imm_clrex) isArg() {}
622
623func (i Imm_clrex) String() string {
624	if i == 15 {
625		return ""
626	}
627	return fmt.Sprintf("#%#x", uint32(i))
628}
629
630// An Imm_dcps is an integer constant for DCPS[123] instruction.
631type Imm_dcps uint16
632
633func (Imm_dcps) isArg() {}
634
635func (i Imm_dcps) String() string {
636	if i == 0 {
637		return ""
638	}
639	return fmt.Sprintf("#%#x", uint32(i))
640}
641
642// Standard conditions.
643type Cond struct {
644	Value  uint8
645	Invert bool
646}
647
648func (Cond) isArg() {}
649
650func (c Cond) String() string {
651	cond31 := c.Value >> 1
652	invert := bool((c.Value & 1) == 1)
653	invert = (invert != c.Invert)
654	switch cond31 {
655	case 0:
656		if invert {
657			return "NE"
658		} else {
659			return "EQ"
660		}
661	case 1:
662		if invert {
663			return "CC"
664		} else {
665			return "CS"
666		}
667	case 2:
668		if invert {
669			return "PL"
670		} else {
671			return "MI"
672		}
673	case 3:
674		if invert {
675			return "VC"
676		} else {
677			return "VS"
678		}
679	case 4:
680		if invert {
681			return "LS"
682		} else {
683			return "HI"
684		}
685	case 5:
686		if invert {
687			return "LT"
688		} else {
689			return "GE"
690		}
691	case 6:
692		if invert {
693			return "LE"
694		} else {
695			return "GT"
696		}
697	case 7:
698		return "AL"
699	}
700	return ""
701}
702
703// An Imm_c is an integer constant for SYS/SYSL/TLBI instruction.
704type Imm_c uint8
705
706func (Imm_c) isArg() {}
707
708func (i Imm_c) String() string {
709	return fmt.Sprintf("C%d", uint8(i))
710}
711
712// An Imm_option is an integer constant for DMB/DSB/ISB instruction.
713type Imm_option uint8
714
715func (Imm_option) isArg() {}
716
717func (i Imm_option) String() string {
718	switch uint8(i) {
719	case 15:
720		return "SY"
721	case 14:
722		return "ST"
723	case 13:
724		return "LD"
725	case 11:
726		return "ISH"
727	case 10:
728		return "ISHST"
729	case 9:
730		return "ISHLD"
731	case 7:
732		return "NSH"
733	case 6:
734		return "NSHST"
735	case 5:
736		return "NSHLD"
737	case 3:
738		return "OSH"
739	case 2:
740		return "OSHST"
741	case 1:
742		return "OSHLD"
743	}
744	return fmt.Sprintf("#%#02x", uint8(i))
745}
746
747// An Imm_prfop is an integer constant for PRFM instruction.
748type Imm_prfop uint8
749
750func (Imm_prfop) isArg() {}
751
752func (i Imm_prfop) String() string {
753	prf_type := (i >> 3) & (1<<2 - 1)
754	prf_target := (i >> 1) & (1<<2 - 1)
755	prf_policy := i & 1
756	var result string
757
758	switch prf_type {
759	case 0:
760		result = "PLD"
761	case 1:
762		result = "PLI"
763	case 2:
764		result = "PST"
765	case 3:
766		return fmt.Sprintf("#%#02x", uint8(i))
767	}
768	switch prf_target {
769	case 0:
770		result += "L1"
771	case 1:
772		result += "L2"
773	case 2:
774		result += "L3"
775	case 3:
776		return fmt.Sprintf("#%#02x", uint8(i))
777	}
778	if prf_policy == 0 {
779		result += "KEEP"
780	} else {
781		result += "STRM"
782	}
783	return result
784}
785
786type Pstatefield uint8
787
788const (
789	SPSel Pstatefield = iota
790	DAIFSet
791	DAIFClr
792)
793
794func (Pstatefield) isArg() {}
795
796func (p Pstatefield) String() string {
797	switch p {
798	case SPSel:
799		return "SPSel"
800	case DAIFSet:
801		return "DAIFSet"
802	case DAIFClr:
803		return "DAIFClr"
804	default:
805		return "unimplemented"
806	}
807}
808
809type Systemreg struct {
810	op0 uint8
811	op1 uint8
812	cn  uint8
813	cm  uint8
814	op2 uint8
815}
816
817func (Systemreg) isArg() {}
818
819func (s Systemreg) String() string {
820	return fmt.Sprintf("S%d_%d_C%d_C%d_%d",
821		s.op0, s.op1, s.cn, s.cm, s.op2)
822}
823
824// An Imm_fp is a signed floating-point constant.
825type Imm_fp struct {
826	s   uint8
827	exp int8
828	pre uint8
829}
830
831func (Imm_fp) isArg() {}
832
833func (i Imm_fp) String() string {
834	var s, pre, numerator, denominator int16
835	var result float64
836	if i.s == 0 {
837		s = 1
838	} else {
839		s = -1
840	}
841	pre = s * int16(16+i.pre)
842	if i.exp > 0 {
843		numerator = (pre << uint8(i.exp))
844		denominator = 16
845	} else {
846		numerator = pre
847		denominator = (16 << uint8(-1*i.exp))
848	}
849	result = float64(numerator) / float64(denominator)
850	return fmt.Sprintf("#%.18e", result)
851}
852
853type Arrangement uint8
854
855const (
856	_ Arrangement = iota
857	ArrangementB
858	Arrangement8B
859	Arrangement16B
860	ArrangementH
861	Arrangement4H
862	Arrangement8H
863	ArrangementS
864	Arrangement2S
865	Arrangement4S
866	ArrangementD
867	Arrangement1D
868	Arrangement2D
869	Arrangement1Q
870)
871
872func (a Arrangement) String() (result string) {
873	switch a {
874	case ArrangementB:
875		result = ".B"
876	case Arrangement8B:
877		result = ".8B"
878	case Arrangement16B:
879		result = ".16B"
880	case ArrangementH:
881		result = ".H"
882	case Arrangement4H:
883		result = ".4H"
884	case Arrangement8H:
885		result = ".8H"
886	case ArrangementS:
887		result = ".S"
888	case Arrangement2S:
889		result = ".2S"
890	case Arrangement4S:
891		result = ".4S"
892	case ArrangementD:
893		result = ".D"
894	case Arrangement1D:
895		result = ".1D"
896	case Arrangement2D:
897		result = ".2D"
898	case Arrangement1Q:
899		result = ".1Q"
900	}
901	return
902}
903
904// Register with arrangement: <Vd>.<T>, { <Vt>.8B, <Vt2>.8B},
905type RegisterWithArrangement struct {
906	r   Reg
907	a   Arrangement
908	cnt uint8
909}
910
911func (RegisterWithArrangement) isArg() {}
912
913func (r RegisterWithArrangement) String() string {
914	result := r.r.String()
915	result += r.a.String()
916	if r.cnt > 0 {
917		result = "{" + result
918		if r.cnt == 2 {
919			r1 := V0 + Reg((uint16(r.r)-uint16(V0)+1)&31)
920			result += ", " + r1.String() + r.a.String()
921		} else if r.cnt > 2 {
922			if (uint16(r.cnt) + ((uint16(r.r) - uint16(V0)) & 31)) > 32 {
923				for i := 1; i < int(r.cnt); i++ {
924					cur := V0 + Reg((uint16(r.r)-uint16(V0)+uint16(i))&31)
925					result += ", " + cur.String() + r.a.String()
926				}
927			} else {
928				r1 := V0 + Reg((uint16(r.r)-uint16(V0)+uint16(r.cnt)-1)&31)
929				result += "-" + r1.String() + r.a.String()
930			}
931		}
932		result += "}"
933	}
934	return result
935}
936
937// Register with arrangement and index:
938//
939//	<Vm>.<Ts>[<index>],
940//	{ <Vt>.B, <Vt2>.B }[<index>].
941type RegisterWithArrangementAndIndex struct {
942	r     Reg
943	a     Arrangement
944	index uint8
945	cnt   uint8
946}
947
948func (RegisterWithArrangementAndIndex) isArg() {}
949
950func (r RegisterWithArrangementAndIndex) String() string {
951	result := r.r.String()
952	result += r.a.String()
953	if r.cnt > 0 {
954		result = "{" + result
955		if r.cnt == 2 {
956			r1 := V0 + Reg((uint16(r.r)-uint16(V0)+1)&31)
957			result += ", " + r1.String() + r.a.String()
958		} else if r.cnt > 2 {
959			if (uint16(r.cnt) + ((uint16(r.r) - uint16(V0)) & 31)) > 32 {
960				for i := 1; i < int(r.cnt); i++ {
961					cur := V0 + Reg((uint16(r.r)-uint16(V0)+uint16(i))&31)
962					result += ", " + cur.String() + r.a.String()
963				}
964			} else {
965				r1 := V0 + Reg((uint16(r.r)-uint16(V0)+uint16(r.cnt)-1)&31)
966				result += "-" + r1.String() + r.a.String()
967			}
968		}
969		result += "}"
970	}
971	return fmt.Sprintf("%s[%d]", result, r.index)
972}
973
974type sysOp struct {
975	op          sysInstFields
976	r           Reg
977	hasOperand2 bool
978}
979
980func (s sysOp) isArg() {}
981
982func (s sysOp) String() string {
983	result := s.op.String()
984	// If s.hasOperand2 is false, the value in the register
985	// specified by s.r is ignored.
986	if s.hasOperand2 {
987		result += ", " + s.r.String()
988	}
989	return result
990}
991
992type sysInstFields struct {
993	op1 uint8
994	cn  uint8
995	cm  uint8
996	op2 uint8
997}
998
999type sysInstAttrs struct {
1000	typ         sys
1001	name        string
1002	hasOperand2 bool
1003}
1004
1005func (s sysInstFields) isArg() {}
1006
1007func (s sysInstFields) getAttrs() sysInstAttrs {
1008	attrs, ok := sysInstsAttrs[sysInstFields{s.op1, s.cn, s.cm, s.op2}]
1009	if !ok {
1010		return sysInstAttrs{typ: sys_SYS}
1011	}
1012	return attrs
1013}
1014
1015func (s sysInstFields) String() string {
1016	return s.getAttrs().name
1017}
1018
1019func (s sysInstFields) getType() sys {
1020	return s.getAttrs().typ
1021}
1022
1023var sysInstsAttrs = map[sysInstFields]sysInstAttrs{
1024	sysInstFields{0, 8, 3, 0}:  {sys_TLBI, "VMALLE1IS", false},
1025	sysInstFields{0, 8, 3, 1}:  {sys_TLBI, "VAE1IS", true},
1026	sysInstFields{0, 8, 3, 2}:  {sys_TLBI, "ASIDE1IS", true},
1027	sysInstFields{0, 8, 3, 3}:  {sys_TLBI, "VAAE1IS", true},
1028	sysInstFields{0, 8, 3, 5}:  {sys_TLBI, "VALE1IS", true},
1029	sysInstFields{0, 8, 3, 7}:  {sys_TLBI, "VAALE1IS", true},
1030	sysInstFields{0, 8, 7, 0}:  {sys_TLBI, "VMALLE1", false},
1031	sysInstFields{0, 8, 7, 1}:  {sys_TLBI, "VAE1", true},
1032	sysInstFields{0, 8, 7, 2}:  {sys_TLBI, "ASIDE1", true},
1033	sysInstFields{0, 8, 7, 3}:  {sys_TLBI, "VAAE1", true},
1034	sysInstFields{0, 8, 7, 5}:  {sys_TLBI, "VALE1", true},
1035	sysInstFields{0, 8, 7, 7}:  {sys_TLBI, "VAALE1", true},
1036	sysInstFields{4, 8, 0, 1}:  {sys_TLBI, "IPAS2E1IS", true},
1037	sysInstFields{4, 8, 0, 5}:  {sys_TLBI, "IPAS2LE1IS", true},
1038	sysInstFields{4, 8, 3, 0}:  {sys_TLBI, "ALLE2IS", false},
1039	sysInstFields{4, 8, 3, 1}:  {sys_TLBI, "VAE2IS", true},
1040	sysInstFields{4, 8, 3, 4}:  {sys_TLBI, "ALLE1IS", false},
1041	sysInstFields{4, 8, 3, 5}:  {sys_TLBI, "VALE2IS", true},
1042	sysInstFields{4, 8, 3, 6}:  {sys_TLBI, "VMALLS12E1IS", false},
1043	sysInstFields{4, 8, 4, 1}:  {sys_TLBI, "IPAS2E1", true},
1044	sysInstFields{4, 8, 4, 5}:  {sys_TLBI, "IPAS2LE1", true},
1045	sysInstFields{4, 8, 7, 0}:  {sys_TLBI, "ALLE2", false},
1046	sysInstFields{4, 8, 7, 1}:  {sys_TLBI, "VAE2", true},
1047	sysInstFields{4, 8, 7, 4}:  {sys_TLBI, "ALLE1", false},
1048	sysInstFields{4, 8, 7, 5}:  {sys_TLBI, "VALE2", true},
1049	sysInstFields{4, 8, 7, 6}:  {sys_TLBI, "VMALLS12E1", false},
1050	sysInstFields{6, 8, 3, 0}:  {sys_TLBI, "ALLE3IS", false},
1051	sysInstFields{6, 8, 3, 1}:  {sys_TLBI, "VAE3IS", true},
1052	sysInstFields{6, 8, 3, 5}:  {sys_TLBI, "VALE3IS", true},
1053	sysInstFields{6, 8, 7, 0}:  {sys_TLBI, "ALLE3", false},
1054	sysInstFields{6, 8, 7, 1}:  {sys_TLBI, "VAE3", true},
1055	sysInstFields{6, 8, 7, 5}:  {sys_TLBI, "VALE3", true},
1056	sysInstFields{0, 8, 1, 0}:  {sys_TLBI, "VMALLE1OS", false},
1057	sysInstFields{0, 8, 1, 1}:  {sys_TLBI, "VAE1OS", true},
1058	sysInstFields{0, 8, 1, 2}:  {sys_TLBI, "ASIDE1OS", true},
1059	sysInstFields{0, 8, 1, 3}:  {sys_TLBI, "VAAE1OS", true},
1060	sysInstFields{0, 8, 1, 5}:  {sys_TLBI, "VALE1OS", true},
1061	sysInstFields{0, 8, 1, 7}:  {sys_TLBI, "VAALE1OS", true},
1062	sysInstFields{0, 8, 2, 1}:  {sys_TLBI, "RVAE1IS", true},
1063	sysInstFields{0, 8, 2, 3}:  {sys_TLBI, "RVAAE1IS", true},
1064	sysInstFields{0, 8, 2, 5}:  {sys_TLBI, "RVALE1IS", true},
1065	sysInstFields{0, 8, 2, 7}:  {sys_TLBI, "RVAALE1IS", true},
1066	sysInstFields{0, 8, 5, 1}:  {sys_TLBI, "RVAE1OS", true},
1067	sysInstFields{0, 8, 5, 3}:  {sys_TLBI, "RVAAE1OS", true},
1068	sysInstFields{0, 8, 5, 5}:  {sys_TLBI, "RVALE1OS", true},
1069	sysInstFields{0, 8, 5, 7}:  {sys_TLBI, "RVAALE1OS", true},
1070	sysInstFields{0, 8, 6, 1}:  {sys_TLBI, "RVAE1", true},
1071	sysInstFields{0, 8, 6, 3}:  {sys_TLBI, "RVAAE1", true},
1072	sysInstFields{0, 8, 6, 5}:  {sys_TLBI, "RVALE1", true},
1073	sysInstFields{0, 8, 6, 7}:  {sys_TLBI, "RVAALE1", true},
1074	sysInstFields{4, 8, 0, 2}:  {sys_TLBI, "RIPAS2E1IS", true},
1075	sysInstFields{4, 8, 0, 6}:  {sys_TLBI, "RIPAS2LE1IS", true},
1076	sysInstFields{4, 8, 1, 0}:  {sys_TLBI, "ALLE2OS", false},
1077	sysInstFields{4, 8, 1, 1}:  {sys_TLBI, "VAE2OS", true},
1078	sysInstFields{4, 8, 1, 4}:  {sys_TLBI, "ALLE1OS", false},
1079	sysInstFields{4, 8, 1, 5}:  {sys_TLBI, "VALE2OS", true},
1080	sysInstFields{4, 8, 1, 6}:  {sys_TLBI, "VMALLS12E1OS", false},
1081	sysInstFields{4, 8, 2, 1}:  {sys_TLBI, "RVAE2IS", true},
1082	sysInstFields{4, 8, 2, 5}:  {sys_TLBI, "RVALE2IS", true},
1083	sysInstFields{4, 8, 4, 0}:  {sys_TLBI, "IPAS2E1OS", true},
1084	sysInstFields{4, 8, 4, 2}:  {sys_TLBI, "RIPAS2E1", true},
1085	sysInstFields{4, 8, 4, 3}:  {sys_TLBI, "RIPAS2E1OS", true},
1086	sysInstFields{4, 8, 4, 4}:  {sys_TLBI, "IPAS2LE1OS", true},
1087	sysInstFields{4, 8, 4, 6}:  {sys_TLBI, "RIPAS2LE1", true},
1088	sysInstFields{4, 8, 4, 7}:  {sys_TLBI, "RIPAS2LE1OS", true},
1089	sysInstFields{4, 8, 5, 1}:  {sys_TLBI, "RVAE2OS", true},
1090	sysInstFields{4, 8, 5, 5}:  {sys_TLBI, "RVALE2OS", true},
1091	sysInstFields{4, 8, 6, 1}:  {sys_TLBI, "RVAE2", true},
1092	sysInstFields{4, 8, 6, 5}:  {sys_TLBI, "RVALE2", true},
1093	sysInstFields{6, 8, 1, 0}:  {sys_TLBI, "ALLE3OS", false},
1094	sysInstFields{6, 8, 1, 1}:  {sys_TLBI, "VAE3OS", true},
1095	sysInstFields{6, 8, 1, 5}:  {sys_TLBI, "VALE3OS", true},
1096	sysInstFields{6, 8, 2, 1}:  {sys_TLBI, "RVAE3IS", true},
1097	sysInstFields{6, 8, 2, 5}:  {sys_TLBI, "RVALE3IS", true},
1098	sysInstFields{6, 8, 5, 1}:  {sys_TLBI, "RVAE3OS", true},
1099	sysInstFields{6, 8, 5, 5}:  {sys_TLBI, "RVALE3OS", true},
1100	sysInstFields{6, 8, 6, 1}:  {sys_TLBI, "RVAE3", true},
1101	sysInstFields{6, 8, 6, 5}:  {sys_TLBI, "RVALE3", true},
1102	sysInstFields{0, 7, 6, 1}:  {sys_DC, "IVAC", true},
1103	sysInstFields{0, 7, 6, 2}:  {sys_DC, "ISW", true},
1104	sysInstFields{0, 7, 10, 2}: {sys_DC, "CSW", true},
1105	sysInstFields{0, 7, 14, 2}: {sys_DC, "CISW", true},
1106	sysInstFields{3, 7, 4, 1}:  {sys_DC, "ZVA", true},
1107	sysInstFields{3, 7, 10, 1}: {sys_DC, "CVAC", true},
1108	sysInstFields{3, 7, 11, 1}: {sys_DC, "CVAU", true},
1109	sysInstFields{3, 7, 14, 1}: {sys_DC, "CIVAC", true},
1110	sysInstFields{0, 7, 6, 3}:  {sys_DC, "IGVAC", true},
1111	sysInstFields{0, 7, 6, 4}:  {sys_DC, "IGSW", true},
1112	sysInstFields{0, 7, 6, 5}:  {sys_DC, "IGDVAC", true},
1113	sysInstFields{0, 7, 6, 6}:  {sys_DC, "IGDSW", true},
1114	sysInstFields{0, 7, 10, 4}: {sys_DC, "CGSW", true},
1115	sysInstFields{0, 7, 10, 6}: {sys_DC, "CGDSW", true},
1116	sysInstFields{0, 7, 14, 4}: {sys_DC, "CIGSW", true},
1117	sysInstFields{0, 7, 14, 6}: {sys_DC, "CIGDSW", true},
1118	sysInstFields{3, 7, 4, 3}:  {sys_DC, "GVA", true},
1119	sysInstFields{3, 7, 4, 4}:  {sys_DC, "GZVA", true},
1120	sysInstFields{3, 7, 10, 3}: {sys_DC, "CGVAC", true},
1121	sysInstFields{3, 7, 10, 5}: {sys_DC, "CGDVAC", true},
1122	sysInstFields{3, 7, 12, 3}: {sys_DC, "CGVAP", true},
1123	sysInstFields{3, 7, 12, 5}: {sys_DC, "CGDVAP", true},
1124	sysInstFields{3, 7, 13, 3}: {sys_DC, "CGVADP", true},
1125	sysInstFields{3, 7, 13, 5}: {sys_DC, "CGDVADP", true},
1126	sysInstFields{3, 7, 14, 3}: {sys_DC, "CIGVAC", true},
1127	sysInstFields{3, 7, 14, 5}: {sys_DC, "CIGDVAC", true},
1128	sysInstFields{3, 7, 12, 1}: {sys_DC, "CVAP", true},
1129	sysInstFields{3, 7, 13, 1}: {sys_DC, "CVADP", true},
1130}
1131