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