...

Source file src/cmd/vendor/golang.org/x/arch/arm64/arm64asm/inst.go

     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		// ShiftMustBeZero is set to true when the shift amount must be 0, even if the
   542		// Amount field is not 0. In GNU syntax, a #0 shift amount is printed if Amount
   543		// is not 0 but ShiftMustBeZero is true; #0 is not printed if Amount is 0 and
   544		// ShiftMustBeZero is true. Both cases represent shift by 0 bit.
   545		ShiftMustBeZero bool
   546	}
   547	
   548	func (MemExtend) isArg() {}
   549	
   550	func (m MemExtend) String() string {
   551		Rbase := m.Base.String()
   552		RIndex := m.Index.String()
   553		if m.ShiftMustBeZero {
   554			if m.Amount != 0 {
   555				return fmt.Sprintf("[%s,%s,%s #0]", Rbase, RIndex, m.Extend.String())
   556			} else {
   557				if m.Extend != lsl {
   558					return fmt.Sprintf("[%s,%s,%s]", Rbase, RIndex, m.Extend.String())
   559				} else {
   560					return fmt.Sprintf("[%s,%s]", Rbase, RIndex)
   561				}
   562			}
   563		} else {
   564			if m.Amount != 0 {
   565				return fmt.Sprintf("[%s,%s,%s #%d]", Rbase, RIndex, m.Extend.String(), m.Amount)
   566			} else {
   567				if m.Extend != lsl {
   568					return fmt.Sprintf("[%s,%s,%s]", Rbase, RIndex, m.Extend.String())
   569				} else {
   570					return fmt.Sprintf("[%s,%s]", Rbase, RIndex)
   571				}
   572			}
   573		}
   574	}
   575	
   576	// An Imm is an integer constant.
   577	type Imm struct {
   578		Imm     uint32
   579		Decimal bool
   580	}
   581	
   582	func (Imm) isArg() {}
   583	
   584	func (i Imm) String() string {
   585		if !i.Decimal {
   586			return fmt.Sprintf("#%#x", i.Imm)
   587		} else {
   588			return fmt.Sprintf("#%d", i.Imm)
   589		}
   590	}
   591	
   592	type Imm64 struct {
   593		Imm     uint64
   594		Decimal bool
   595	}
   596	
   597	func (Imm64) isArg() {}
   598	
   599	func (i Imm64) String() string {
   600		if !i.Decimal {
   601			return fmt.Sprintf("#%#x", i.Imm)
   602		} else {
   603			return fmt.Sprintf("#%d", i.Imm)
   604		}
   605	}
   606	
   607	// An Imm_hint is an integer constant for HINT instruction.
   608	type Imm_hint uint8
   609	
   610	func (Imm_hint) isArg() {}
   611	
   612	func (i Imm_hint) String() string {
   613		return fmt.Sprintf("#%#x", uint32(i))
   614	}
   615	
   616	// An Imm_clrex is an integer constant for CLREX instruction.
   617	type Imm_clrex uint8
   618	
   619	func (Imm_clrex) isArg() {}
   620	
   621	func (i Imm_clrex) String() string {
   622		if i == 15 {
   623			return ""
   624		}
   625		return fmt.Sprintf("#%#x", uint32(i))
   626	}
   627	
   628	// An Imm_dcps is an integer constant for DCPS[123] instruction.
   629	type Imm_dcps uint16
   630	
   631	func (Imm_dcps) isArg() {}
   632	
   633	func (i Imm_dcps) String() string {
   634		if i == 0 {
   635			return ""
   636		}
   637		return fmt.Sprintf("#%#x", uint32(i))
   638	}
   639	
   640	// Standard conditions.
   641	type Cond struct {
   642		Value  uint8
   643		Invert bool
   644	}
   645	
   646	func (Cond) isArg() {}
   647	
   648	func (c Cond) String() string {
   649		cond31 := c.Value >> 1
   650		invert := bool((c.Value & 1) == 1)
   651		invert = (invert != c.Invert)
   652		switch cond31 {
   653		case 0:
   654			if invert {
   655				return "NE"
   656			} else {
   657				return "EQ"
   658			}
   659		case 1:
   660			if invert {
   661				return "CC"
   662			} else {
   663				return "CS"
   664			}
   665		case 2:
   666			if invert {
   667				return "PL"
   668			} else {
   669				return "MI"
   670			}
   671		case 3:
   672			if invert {
   673				return "VC"
   674			} else {
   675				return "VS"
   676			}
   677		case 4:
   678			if invert {
   679				return "LS"
   680			} else {
   681				return "HI"
   682			}
   683		case 5:
   684			if invert {
   685				return "LT"
   686			} else {
   687				return "GE"
   688			}
   689		case 6:
   690			if invert {
   691				return "LE"
   692			} else {
   693				return "GT"
   694			}
   695		case 7:
   696			return "AL"
   697		}
   698		return ""
   699	}
   700	
   701	// An Imm_c is an integer constant for SYS/SYSL/TLBI instruction.
   702	type Imm_c uint8
   703	
   704	func (Imm_c) isArg() {}
   705	
   706	func (i Imm_c) String() string {
   707		return fmt.Sprintf("C%d", uint8(i))
   708	}
   709	
   710	// An Imm_option is an integer constant for DMB/DSB/ISB instruction.
   711	type Imm_option uint8
   712	
   713	func (Imm_option) isArg() {}
   714	
   715	func (i Imm_option) String() string {
   716		switch uint8(i) {
   717		case 15:
   718			return "SY"
   719		case 14:
   720			return "ST"
   721		case 13:
   722			return "LD"
   723		case 11:
   724			return "ISH"
   725		case 10:
   726			return "ISHST"
   727		case 9:
   728			return "ISHLD"
   729		case 7:
   730			return "NSH"
   731		case 6:
   732			return "NSHST"
   733		case 5:
   734			return "NSHLD"
   735		case 3:
   736			return "OSH"
   737		case 2:
   738			return "OSHST"
   739		case 1:
   740			return "OSHLD"
   741		}
   742		return fmt.Sprintf("#%#02x", uint8(i))
   743	}
   744	
   745	// An Imm_prfop is an integer constant for PRFM instruction.
   746	type Imm_prfop uint8
   747	
   748	func (Imm_prfop) isArg() {}
   749	
   750	func (i Imm_prfop) String() string {
   751		prf_type := (i >> 3) & (1<<2 - 1)
   752		prf_target := (i >> 1) & (1<<2 - 1)
   753		prf_policy := i & 1
   754		var result string
   755	
   756		switch prf_type {
   757		case 0:
   758			result = "PLD"
   759		case 1:
   760			result = "PLI"
   761		case 2:
   762			result = "PST"
   763		case 3:
   764			return fmt.Sprintf("#%#02x", uint8(i))
   765		}
   766		switch prf_target {
   767		case 0:
   768			result += "L1"
   769		case 1:
   770			result += "L2"
   771		case 2:
   772			result += "L3"
   773		case 3:
   774			return fmt.Sprintf("#%#02x", uint8(i))
   775		}
   776		if prf_policy == 0 {
   777			result += "KEEP"
   778		} else {
   779			result += "STRM"
   780		}
   781		return result
   782	}
   783	
   784	type Pstatefield uint8
   785	
   786	const (
   787		SPSel Pstatefield = iota
   788		DAIFSet
   789		DAIFClr
   790	)
   791	
   792	func (Pstatefield) isArg() {}
   793	
   794	func (p Pstatefield) String() string {
   795		switch p {
   796		case SPSel:
   797			return "SPSel"
   798		case DAIFSet:
   799			return "DAIFSet"
   800		case DAIFClr:
   801			return "DAIFClr"
   802		default:
   803			return "unimplemented"
   804		}
   805	}
   806	
   807	type Systemreg struct {
   808		op0 uint8
   809		op1 uint8
   810		cn  uint8
   811		cm  uint8
   812		op2 uint8
   813	}
   814	
   815	func (Systemreg) isArg() {}
   816	
   817	func (s Systemreg) String() string {
   818		return fmt.Sprintf("S%d_%d_C%d_C%d_%d",
   819			s.op0, s.op1, s.cn, s.cm, s.op2)
   820	}
   821	
   822	// An Imm_fp is a signed floating-point constant.
   823	type Imm_fp struct {
   824		s   uint8
   825		exp int8
   826		pre uint8
   827	}
   828	
   829	func (Imm_fp) isArg() {}
   830	
   831	func (i Imm_fp) String() string {
   832		var s, pre, numerator, denominator int16
   833		var result float64
   834		if i.s == 0 {
   835			s = 1
   836		} else {
   837			s = -1
   838		}
   839		pre = s * int16(16+i.pre)
   840		if i.exp > 0 {
   841			numerator = (pre << uint8(i.exp))
   842			denominator = 16
   843		} else {
   844			numerator = pre
   845			denominator = (16 << uint8(-1*i.exp))
   846		}
   847		result = float64(numerator) / float64(denominator)
   848		return fmt.Sprintf("#%.18e", result)
   849	}
   850	
   851	type Arrangement uint8
   852	
   853	const (
   854		_ Arrangement = iota
   855		ArrangementB
   856		Arrangement8B
   857		Arrangement16B
   858		ArrangementH
   859		Arrangement4H
   860		Arrangement8H
   861		ArrangementS
   862		Arrangement2S
   863		Arrangement4S
   864		ArrangementD
   865		Arrangement1D
   866		Arrangement2D
   867		Arrangement1Q
   868	)
   869	
   870	func (a Arrangement) String() (result string) {
   871		switch a {
   872		case ArrangementB:
   873			result = ".B"
   874		case Arrangement8B:
   875			result = ".8B"
   876		case Arrangement16B:
   877			result = ".16B"
   878		case ArrangementH:
   879			result = ".H"
   880		case Arrangement4H:
   881			result = ".4H"
   882		case Arrangement8H:
   883			result = ".8H"
   884		case ArrangementS:
   885			result = ".S"
   886		case Arrangement2S:
   887			result = ".2S"
   888		case Arrangement4S:
   889			result = ".4S"
   890		case ArrangementD:
   891			result = ".D"
   892		case Arrangement1D:
   893			result = ".1D"
   894		case Arrangement2D:
   895			result = ".2D"
   896		case Arrangement1Q:
   897			result = ".1Q"
   898		}
   899		return
   900	}
   901	
   902	// Register with arrangement: <Vd>.<T>, { <Vt>.8B, <Vt2>.8B},
   903	type RegisterWithArrangement struct {
   904		r   Reg
   905		a   Arrangement
   906		cnt uint8
   907	}
   908	
   909	func (RegisterWithArrangement) isArg() {}
   910	
   911	func (r RegisterWithArrangement) String() string {
   912		result := r.r.String()
   913		result += r.a.String()
   914		if r.cnt > 0 {
   915			result = "{" + result
   916			if r.cnt == 2 {
   917				r1 := V0 + Reg((uint16(r.r)-uint16(V0)+1)&31)
   918				result += ", " + r1.String() + r.a.String()
   919			} else if r.cnt > 2 {
   920				if (uint16(r.cnt) + ((uint16(r.r) - uint16(V0)) & 31)) > 32 {
   921					for i := 1; i < int(r.cnt); i++ {
   922						cur := V0 + Reg((uint16(r.r)-uint16(V0)+uint16(i))&31)
   923						result += ", " + cur.String() + r.a.String()
   924					}
   925				} else {
   926					r1 := V0 + Reg((uint16(r.r)-uint16(V0)+uint16(r.cnt)-1)&31)
   927					result += "-" + r1.String() + r.a.String()
   928				}
   929			}
   930			result += "}"
   931		}
   932		return result
   933	}
   934	
   935	// Register with arrangement and index: <Vm>.<Ts>[<index>],
   936	//   { <Vt>.B, <Vt2>.B }[<index>].
   937	type RegisterWithArrangementAndIndex struct {
   938		r     Reg
   939		a     Arrangement
   940		index uint8
   941		cnt   uint8
   942	}
   943	
   944	func (RegisterWithArrangementAndIndex) isArg() {}
   945	
   946	func (r RegisterWithArrangementAndIndex) String() string {
   947		result := r.r.String()
   948		result += r.a.String()
   949		if r.cnt > 0 {
   950			result = "{" + result
   951			if r.cnt == 2 {
   952				r1 := V0 + Reg((uint16(r.r)-uint16(V0)+1)&31)
   953				result += ", " + r1.String() + r.a.String()
   954			} else if r.cnt > 2 {
   955				if (uint16(r.cnt) + ((uint16(r.r) - uint16(V0)) & 31)) > 32 {
   956					for i := 1; i < int(r.cnt); i++ {
   957						cur := V0 + Reg((uint16(r.r)-uint16(V0)+uint16(i))&31)
   958						result += ", " + cur.String() + r.a.String()
   959					}
   960				} else {
   961					r1 := V0 + Reg((uint16(r.r)-uint16(V0)+uint16(r.cnt)-1)&31)
   962					result += "-" + r1.String() + r.a.String()
   963				}
   964			}
   965			result += "}"
   966		}
   967		return fmt.Sprintf("%s[%d]", result, r.index)
   968	}
   969	

View as plain text