github.com/bir3/gocompiler@v0.9.2202/src/xvendor/golang.org/x/arch/arm64/arm64asm/inst.go (about)

     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  
     5  package arm64asm
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  )
    11  
    12  // An Op is an ARM64 opcode.
    13  type 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  
    20  func (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.
    28  type Inst struct {
    29  	Op   Op     // Opcode mnemonic
    30  	Enc  uint32 // Raw encoding bits.
    31  	Args Args   // Instruction arguments, in ARM manual order.
    32  }
    33  
    34  func (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.
    48  type 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.
    55  type 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.
    62  type Reg uint16
    63  
    64  const (
    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  
   333  func (Reg) isArg() {}
   334  
   335  func (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.
   365  type RegSP Reg
   366  
   367  func (RegSP) isArg() {}
   368  
   369  func (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  
   380  type ImmShift struct {
   381  	imm   uint16
   382  	shift uint8
   383  }
   384  
   385  func (ImmShift) isArg() {}
   386  
   387  func (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  
   397  type ExtShift uint8
   398  
   399  const (
   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  
   415  func (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  
   456  type RegExtshiftAmount struct {
   457  	reg       Reg
   458  	extShift  ExtShift
   459  	amount    uint8
   460  	show_zero bool
   461  }
   462  
   463  func (RegExtshiftAmount) isArg() {}
   464  
   465  func (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.
   482  type PCRel int64
   483  
   484  func (PCRel) isArg() {}
   485  
   486  func (r PCRel) String() string {
   487  	return fmt.Sprintf(".%+#x", uint64(r))
   488  }
   489  
   490  // An AddrMode is an ARM addressing mode.
   491  type AddrMode uint8
   492  
   493  const (
   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.
   503  type MemImmediate struct {
   504  	Base RegSP
   505  	Mode AddrMode
   506  	imm  int32
   507  }
   508  
   509  func (MemImmediate) isArg() {}
   510  
   511  func (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.
   535  type 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  
   550  func (MemExtend) isArg() {}
   551  
   552  func (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.
   579  type Imm struct {
   580  	Imm     uint32
   581  	Decimal bool
   582  }
   583  
   584  func (Imm) isArg() {}
   585  
   586  func (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  
   594  type Imm64 struct {
   595  	Imm     uint64
   596  	Decimal bool
   597  }
   598  
   599  func (Imm64) isArg() {}
   600  
   601  func (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.
   610  type Imm_hint uint8
   611  
   612  func (Imm_hint) isArg() {}
   613  
   614  func (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.
   619  type Imm_clrex uint8
   620  
   621  func (Imm_clrex) isArg() {}
   622  
   623  func (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.
   631  type Imm_dcps uint16
   632  
   633  func (Imm_dcps) isArg() {}
   634  
   635  func (i Imm_dcps) String() string {
   636  	if i == 0 {
   637  		return ""
   638  	}
   639  	return fmt.Sprintf("#%#x", uint32(i))
   640  }
   641  
   642  // Standard conditions.
   643  type Cond struct {
   644  	Value  uint8
   645  	Invert bool
   646  }
   647  
   648  func (Cond) isArg() {}
   649  
   650  func (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.
   704  type Imm_c uint8
   705  
   706  func (Imm_c) isArg() {}
   707  
   708  func (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.
   713  type Imm_option uint8
   714  
   715  func (Imm_option) isArg() {}
   716  
   717  func (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.
   748  type Imm_prfop uint8
   749  
   750  func (Imm_prfop) isArg() {}
   751  
   752  func (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  
   786  type Pstatefield uint8
   787  
   788  const (
   789  	SPSel Pstatefield = iota
   790  	DAIFSet
   791  	DAIFClr
   792  )
   793  
   794  func (Pstatefield) isArg() {}
   795  
   796  func (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  
   809  type Systemreg struct {
   810  	op0 uint8
   811  	op1 uint8
   812  	cn  uint8
   813  	cm  uint8
   814  	op2 uint8
   815  }
   816  
   817  func (Systemreg) isArg() {}
   818  
   819  func (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.
   825  type Imm_fp struct {
   826  	s   uint8
   827  	exp int8
   828  	pre uint8
   829  }
   830  
   831  func (Imm_fp) isArg() {}
   832  
   833  func (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  
   853  type Arrangement uint8
   854  
   855  const (
   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  
   872  func (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},
   905  type RegisterWithArrangement struct {
   906  	r   Reg
   907  	a   Arrangement
   908  	cnt uint8
   909  }
   910  
   911  func (RegisterWithArrangement) isArg() {}
   912  
   913  func (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>].
   941  type RegisterWithArrangementAndIndex struct {
   942  	r     Reg
   943  	a     Arrangement
   944  	index uint8
   945  	cnt   uint8
   946  }
   947  
   948  func (RegisterWithArrangementAndIndex) isArg() {}
   949  
   950  func (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  
   974  type sysOp struct {
   975  	op          sysInstFields
   976  	r           Reg
   977  	hasOperand2 bool
   978  }
   979  
   980  func (s sysOp) isArg() {}
   981  
   982  func (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  
   992  type sysInstFields struct {
   993  	op1 uint8
   994  	cn  uint8
   995  	cm  uint8
   996  	op2 uint8
   997  }
   998  
   999  type sysInstAttrs struct {
  1000  	typ         sys
  1001  	name        string
  1002  	hasOperand2 bool
  1003  }
  1004  
  1005  func (s sysInstFields) isArg() {}
  1006  
  1007  func (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  
  1015  func (s sysInstFields) String() string {
  1016  	return s.getAttrs().name
  1017  }
  1018  
  1019  func (s sysInstFields) getType() sys {
  1020  	return s.getAttrs().typ
  1021  }
  1022  
  1023  var 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  }