...

Source file src/cmd/vendor/golang.org/x/arch/arm64/arm64asm/plan9x.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		"io"
    10		"sort"
    11		"strings"
    12	)
    13	
    14	// GoSyntax returns the Go assembler syntax for the instruction.
    15	// The syntax was originally defined by Plan 9.
    16	// The pc is the program counter of the instruction, used for
    17	// expanding PC-relative addresses into absolute ones.
    18	// The symname function queries the symbol table for the program
    19	// being disassembled. Given a target address it returns the name
    20	// and base address of the symbol containing the target, if any;
    21	// otherwise it returns "", 0.
    22	// The reader text should read from the text segment using text addresses
    23	// as offsets; it is used to display pc-relative loads as constant loads.
    24	func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string {
    25		if symname == nil {
    26			symname = func(uint64) (string, uint64) { return "", 0 }
    27		}
    28	
    29		var args []string
    30		for _, a := range inst.Args {
    31			if a == nil {
    32				break
    33			}
    34			args = append(args, plan9Arg(&inst, pc, symname, a))
    35		}
    36	
    37		op := inst.Op.String()
    38	
    39		switch inst.Op {
    40		case LDR, LDRB, LDRH, LDRSB, LDRSH, LDRSW:
    41			// Check for PC-relative load.
    42			if offset, ok := inst.Args[1].(PCRel); ok {
    43				addr := pc + uint64(offset)
    44				if _, ok := inst.Args[0].(Reg); !ok {
    45					break
    46				}
    47				if s, base := symname(addr); s != "" && addr == base {
    48					args[1] = fmt.Sprintf("$%s(SB)", s)
    49				}
    50			}
    51		}
    52	
    53		// Move addressing mode into opcode suffix.
    54		suffix := ""
    55		switch inst.Op {
    56		case LDR, LDRB, LDRH, LDRSB, LDRSH, LDRSW, STR, STRB, STRH, STUR, STURB, STURH, LD1, ST1:
    57			switch mem := inst.Args[1].(type) {
    58			case MemImmediate:
    59				switch mem.Mode {
    60				case AddrOffset:
    61					// no suffix
    62				case AddrPreIndex:
    63					suffix = ".W"
    64				case AddrPostIndex, AddrPostReg:
    65					suffix = ".P"
    66				}
    67			}
    68	
    69		case STP, LDP:
    70			switch mem := inst.Args[2].(type) {
    71			case MemImmediate:
    72				switch mem.Mode {
    73				case AddrOffset:
    74					// no suffix
    75				case AddrPreIndex:
    76					suffix = ".W"
    77				case AddrPostIndex:
    78					suffix = ".P"
    79				}
    80			}
    81		}
    82	
    83		switch inst.Op {
    84		case BL:
    85			return "CALL " + args[0]
    86	
    87		case BLR:
    88			r := inst.Args[0].(Reg)
    89			regno := uint16(r) & 31
    90			return fmt.Sprintf("CALL (R%d)", regno)
    91	
    92		case RET:
    93			if r, ok := inst.Args[0].(Reg); ok && r == X30 {
    94				return "RET"
    95			}
    96	
    97		case B:
    98			if cond, ok := inst.Args[0].(Cond); ok {
    99				return "B" + cond.String() + " " + args[1]
   100			}
   101			return "JMP" + " " + args[0]
   102	
   103		case BR:
   104			r := inst.Args[0].(Reg)
   105			regno := uint16(r) & 31
   106			return fmt.Sprintf("JMP (R%d)", regno)
   107	
   108		case MOV:
   109			rno := -1
   110			switch a := inst.Args[0].(type) {
   111			case Reg:
   112				rno = int(a)
   113			case RegSP:
   114				rno = int(a)
   115			case RegisterWithArrangementAndIndex:
   116				op = "VMOV"
   117			case RegisterWithArrangement:
   118				op = "VMOV"
   119			}
   120			if rno >= 0 && rno <= int(WZR) {
   121				op = "MOVW"
   122			} else if rno >= int(X0) && rno <= int(XZR) {
   123				op = "MOVD"
   124			}
   125			if _, ok := inst.Args[1].(RegisterWithArrangementAndIndex); ok {
   126				op = "VMOV"
   127			}
   128	
   129		case LDR:
   130			var rno uint16
   131			if r, ok := inst.Args[0].(Reg); ok {
   132				rno = uint16(r)
   133			} else {
   134				rno = uint16(inst.Args[0].(RegSP))
   135			}
   136			if rno <= uint16(WZR) {
   137				op = "MOVWU" + suffix
   138			} else if rno >= uint16(S0) && rno <= uint16(S31) {
   139				op = "FMOVS" + suffix
   140				args[0] = fmt.Sprintf("F%d", rno&31)
   141			} else if rno >= uint16(D0) && rno <= uint16(D31) {
   142				op = "FMOVD" + suffix
   143				args[0] = fmt.Sprintf("F%d", rno&31)
   144			} else {
   145				op = "MOVD" + suffix
   146			}
   147	
   148		case LDRB:
   149			op = "MOVBU" + suffix
   150	
   151		case LDRH:
   152			op = "MOVHU" + suffix
   153	
   154		case LDRSW:
   155			op = "MOVW" + suffix
   156	
   157		case LDRSB:
   158			if r, ok := inst.Args[0].(Reg); ok {
   159				rno := uint16(r)
   160				if rno <= uint16(WZR) {
   161					op = "MOVBW" + suffix
   162				} else {
   163					op = "MOVB" + suffix
   164				}
   165			}
   166		case LDRSH:
   167			if r, ok := inst.Args[0].(Reg); ok {
   168				rno := uint16(r)
   169				if rno <= uint16(WZR) {
   170					op = "MOVHW" + suffix
   171				} else {
   172					op = "MOVH" + suffix
   173				}
   174			}
   175		case STR, STUR:
   176			var rno uint16
   177			if r, ok := inst.Args[0].(Reg); ok {
   178				rno = uint16(r)
   179			} else {
   180				rno = uint16(inst.Args[0].(RegSP))
   181			}
   182			if rno <= uint16(WZR) {
   183				op = "MOVW" + suffix
   184			} else if rno >= uint16(S0) && rno <= uint16(S31) {
   185				op = "FMOVS" + suffix
   186				args[0] = fmt.Sprintf("F%d", rno&31)
   187			} else if rno >= uint16(D0) && rno <= uint16(D31) {
   188				op = "FMOVD" + suffix
   189				args[0] = fmt.Sprintf("F%d", rno&31)
   190			} else {
   191				op = "MOVD" + suffix
   192			}
   193			args[0], args[1] = args[1], args[0]
   194	
   195		case STRB, STURB:
   196			op = "MOVB" + suffix
   197			args[0], args[1] = args[1], args[0]
   198	
   199		case STRH, STURH:
   200			op = "MOVH" + suffix
   201			args[0], args[1] = args[1], args[0]
   202	
   203		case TBNZ, TBZ:
   204			args[0], args[1], args[2] = args[2], args[0], args[1]
   205	
   206		case MADD, MSUB, SMADDL, SMSUBL, UMADDL, UMSUBL:
   207			if r, ok := inst.Args[0].(Reg); ok {
   208				rno := uint16(r)
   209				if rno <= uint16(WZR) {
   210					op += "W"
   211				}
   212			}
   213			args[2], args[3] = args[3], args[2]
   214		case STLR:
   215			if r, ok := inst.Args[0].(Reg); ok {
   216				rno := uint16(r)
   217				if rno <= uint16(WZR) {
   218					op += "W"
   219				}
   220			}
   221			args[0], args[1] = args[1], args[0]
   222	
   223		case STLRB, STLRH:
   224			args[0], args[1] = args[1], args[0]
   225	
   226		case STLXR, STXR:
   227			if r, ok := inst.Args[1].(Reg); ok {
   228				rno := uint16(r)
   229				if rno <= uint16(WZR) {
   230					op += "W"
   231				}
   232			}
   233			args[1], args[2] = args[2], args[1]
   234	
   235		case STLXRB, STLXRH, STXRB, STXRH:
   236			args[1], args[2] = args[2], args[1]
   237	
   238		case BFI, BFXIL, SBFIZ, SBFX, UBFIZ, UBFX:
   239			if r, ok := inst.Args[0].(Reg); ok {
   240				rno := uint16(r)
   241				if rno <= uint16(WZR) {
   242					op += "W"
   243				}
   244			}
   245			args[1], args[2], args[3] = args[3], args[1], args[2]
   246	
   247		case LDAXP, LDXP:
   248			if r, ok := inst.Args[0].(Reg); ok {
   249				rno := uint16(r)
   250				if rno <= uint16(WZR) {
   251					op += "W"
   252				}
   253			}
   254			fallthrough
   255	
   256		case STP, LDP:
   257			args[0] = fmt.Sprintf("(%s, %s)", args[0], args[1])
   258			args[1] = args[2]
   259			if op == "STP" {
   260				op = op + suffix
   261				return op + " " + args[0] + ", " + args[1]
   262			} else if op == "LDP" {
   263				op = op + suffix
   264				return op + " " + args[1] + ", " + args[0]
   265			} else if op == "LDAXP" || op == "LDXP" || op == "LDAXPW" || op == "LDXPW" {
   266				return op + " " + args[1] + ", " + args[0]
   267			}
   268	
   269		case STLXP, STXP:
   270			if r, ok := inst.Args[1].(Reg); ok {
   271				rno := uint16(r)
   272				if rno <= uint16(WZR) {
   273					op += "W"
   274				}
   275			}
   276			args[1] = fmt.Sprintf("(%s, %s)", args[1], args[2])
   277			args[2] = args[3]
   278			return op + " " + args[1] + ", " + args[2] + ", " + args[0]
   279	
   280		case FCCMP, FCCMPE:
   281			args[0], args[1] = args[1], args[0]
   282			fallthrough
   283	
   284		case FCMP, FCMPE:
   285			if _, ok := inst.Args[1].(Imm); ok {
   286				args[1] = "$(0.0)"
   287			}
   288			fallthrough
   289	
   290		case FADD, FSUB, FMUL, FNMUL, FDIV, FMAX, FMIN, FMAXNM, FMINNM, FCSEL, FMADD, FMSUB, FNMADD, FNMSUB:
   291			if strings.HasSuffix(op, "MADD") || strings.HasSuffix(op, "MSUB") {
   292				args[2], args[3] = args[3], args[2]
   293			}
   294			if r, ok := inst.Args[0].(Reg); ok {
   295				rno := uint16(r)
   296				if rno >= uint16(S0) && rno <= uint16(S31) {
   297					op = fmt.Sprintf("%sS", op)
   298				} else if rno >= uint16(D0) && rno <= uint16(D31) {
   299					op = fmt.Sprintf("%sD", op)
   300				}
   301			}
   302	
   303		case FCVT:
   304			for i := 1; i >= 0; i-- {
   305				if r, ok := inst.Args[i].(Reg); ok {
   306					rno := uint16(r)
   307					if rno >= uint16(H0) && rno <= uint16(H31) {
   308						op = fmt.Sprintf("%sH", op)
   309					} else if rno >= uint16(S0) && rno <= uint16(S31) {
   310						op = fmt.Sprintf("%sS", op)
   311					} else if rno >= uint16(D0) && rno <= uint16(D31) {
   312						op = fmt.Sprintf("%sD", op)
   313					}
   314				}
   315			}
   316	
   317		case FABS, FNEG, FSQRT, FRINTN, FRINTP, FRINTM, FRINTZ, FRINTA, FRINTX, FRINTI:
   318			if r, ok := inst.Args[1].(Reg); ok {
   319				rno := uint16(r)
   320				if rno >= uint16(S0) && rno <= uint16(S31) {
   321					op = fmt.Sprintf("%sS", op)
   322				} else if rno >= uint16(D0) && rno <= uint16(D31) {
   323					op = fmt.Sprintf("%sD", op)
   324				}
   325			}
   326	
   327		case FCVTZS, FCVTZU, SCVTF, UCVTF:
   328			if _, ok := inst.Args[2].(Imm); !ok {
   329				for i := 1; i >= 0; i-- {
   330					if r, ok := inst.Args[i].(Reg); ok {
   331						rno := uint16(r)
   332						if rno >= uint16(S0) && rno <= uint16(S31) {
   333							op = fmt.Sprintf("%sS", op)
   334						} else if rno >= uint16(D0) && rno <= uint16(D31) {
   335							op = fmt.Sprintf("%sD", op)
   336						} else if rno <= uint16(WZR) {
   337							op += "W"
   338						}
   339					}
   340				}
   341			}
   342	
   343		case FMOV:
   344			for i := 0; i <= 1; i++ {
   345				if r, ok := inst.Args[i].(Reg); ok {
   346					rno := uint16(r)
   347					if rno >= uint16(S0) && rno <= uint16(S31) {
   348						op = fmt.Sprintf("%sS", op)
   349						break
   350					} else if rno >= uint16(D0) && rno <= uint16(D31) {
   351						op = fmt.Sprintf("%sD", op)
   352						break
   353					}
   354				}
   355			}
   356	
   357		case SYSL:
   358			op1 := int(inst.Args[1].(Imm).Imm)
   359			cn := int(inst.Args[2].(Imm_c))
   360			cm := int(inst.Args[3].(Imm_c))
   361			op2 := int(inst.Args[4].(Imm).Imm)
   362			sysregno := int32(op1<<16 | cn<<12 | cm<<8 | op2<<5)
   363			args[1] = fmt.Sprintf("$%d", sysregno)
   364			return op + " " + args[1] + ", " + args[0]
   365	
   366		case CBNZ, CBZ:
   367			if r, ok := inst.Args[0].(Reg); ok {
   368				rno := uint16(r)
   369				if rno <= uint16(WZR) {
   370					op += "W"
   371				}
   372			}
   373			args[0], args[1] = args[1], args[0]
   374	
   375		case ADR, ADRP:
   376			addr := int64(inst.Args[1].(PCRel))
   377			args[1] = fmt.Sprintf("%d(PC)", addr)
   378	
   379		case MSR:
   380			args[0] = inst.Args[0].String()
   381	
   382		case ST1:
   383			op = fmt.Sprintf("V%s", op) + suffix
   384			args[0], args[1] = args[1], args[0]
   385	
   386		case LD1:
   387			op = fmt.Sprintf("V%s", op) + suffix
   388	
   389		case UMOV:
   390			op = "VMOV"
   391	
   392		default:
   393			index := sort.SearchStrings(noSuffixOpSet, op)
   394			if !(index < len(noSuffixOpSet) && noSuffixOpSet[index] == op) {
   395				rno := -1
   396				switch a := inst.Args[0].(type) {
   397				case Reg:
   398					rno = int(a)
   399				case RegSP:
   400					rno = int(a)
   401				case RegisterWithArrangement:
   402					op = fmt.Sprintf("V%s", op)
   403				}
   404	
   405				if rno >= int(B0) && rno <= int(Q31) && !strings.HasPrefix(op, "F") {
   406					op = fmt.Sprintf("V%s", op)
   407				}
   408				if rno >= 0 && rno <= int(WZR) {
   409					// Add "w" to opcode suffix.
   410					op += "W"
   411				}
   412			}
   413			op = op + suffix
   414		}
   415	
   416		// conditional instructions, replace args.
   417		if _, ok := inst.Args[3].(Cond); ok {
   418			if _, ok := inst.Args[2].(Reg); ok {
   419				args[1], args[2] = args[2], args[1]
   420			} else {
   421				args[0], args[2] = args[2], args[0]
   422			}
   423		}
   424		// Reverse args, placing dest last.
   425		for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
   426			args[i], args[j] = args[j], args[i]
   427		}
   428	
   429		if args != nil {
   430			op += " " + strings.Join(args, ", ")
   431		}
   432	
   433		return op
   434	}
   435	
   436	// No need add "W" to opcode suffix.
   437	// Opcode must be inserted in ascending order.
   438	var noSuffixOpSet = strings.Fields(`
   439	AESD
   440	AESE
   441	AESIMC
   442	AESMC
   443	CRC32B
   444	CRC32CB
   445	CRC32CH
   446	CRC32CW
   447	CRC32CX
   448	CRC32H
   449	CRC32W
   450	CRC32X
   451	LDARB
   452	LDARH
   453	LDAXRB
   454	LDAXRH
   455	LDTRH
   456	LDXRB
   457	LDXRH
   458	SHA1C
   459	SHA1H
   460	SHA1M
   461	SHA1P
   462	SHA1SU0
   463	SHA1SU1
   464	SHA256H
   465	SHA256H2
   466	SHA256SU0
   467	SHA256SU1
   468	`)
   469	
   470	func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
   471		switch a := arg.(type) {
   472		case Imm:
   473			return fmt.Sprintf("$%d", uint32(a.Imm))
   474	
   475		case Imm64:
   476			return fmt.Sprintf("$%d", int64(a.Imm))
   477	
   478		case ImmShift:
   479			if a.shift == 0 {
   480				return fmt.Sprintf("$%d", a.imm)
   481			}
   482			return fmt.Sprintf("$(%d<<%d)", a.imm, a.shift)
   483	
   484		case PCRel:
   485			addr := int64(pc) + int64(a)
   486			if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base {
   487				return fmt.Sprintf("%s(SB)", s)
   488			}
   489			return fmt.Sprintf("%d(PC)", a/4)
   490	
   491		case Reg:
   492			regenum := uint16(a)
   493			regno := uint16(a) & 31
   494	
   495			if regenum >= uint16(B0) && regenum <= uint16(D31) {
   496				if strings.HasPrefix(inst.Op.String(), "F") || strings.HasSuffix(inst.Op.String(), "CVTF") {
   497					// FP registers are the same ones as SIMD registers
   498					// Print Fn for scalar variant to align with assembler (e.g., FCVT, SCVTF, UCVTF, etc.)
   499					return fmt.Sprintf("F%d", regno)
   500				} else {
   501					return fmt.Sprintf("V%d", regno)
   502				}
   503	
   504			} else if regenum >= uint16(Q0) && regenum <= uint16(Q31) {
   505				// Print Vn to align with assembler (e.g., SHA256H)
   506				return fmt.Sprintf("V%d", regno)
   507			}
   508	
   509			if regno == 31 {
   510				return "ZR"
   511			}
   512			return fmt.Sprintf("R%d", regno)
   513	
   514		case RegSP:
   515			regno := uint16(a) & 31
   516			if regno == 31 {
   517				return "RSP"
   518			}
   519			return fmt.Sprintf("R%d", regno)
   520	
   521		case RegExtshiftAmount:
   522			reg := ""
   523			regno := uint16(a.reg) & 31
   524			if regno == 31 {
   525				reg = "ZR"
   526			} else {
   527				reg = fmt.Sprintf("R%d", uint16(a.reg)&31)
   528			}
   529			extshift := ""
   530			amount := ""
   531			if a.extShift != ExtShift(0) {
   532				switch a.extShift {
   533				default:
   534					extshift = "." + a.extShift.String()
   535	
   536				case lsl:
   537					extshift = "<<"
   538					amount = fmt.Sprintf("%d", a.amount)
   539					return reg + extshift + amount
   540	
   541				case lsr:
   542					extshift = ">>"
   543					amount = fmt.Sprintf("%d", a.amount)
   544					return reg + extshift + amount
   545	
   546				case asr:
   547					extshift = "->"
   548					amount = fmt.Sprintf("%d", a.amount)
   549					return reg + extshift + amount
   550				case ror:
   551					extshift = "@>"
   552					amount = fmt.Sprintf("%d", a.amount)
   553					return reg + extshift + amount
   554				}
   555				if a.amount != 0 {
   556					amount = fmt.Sprintf("<<%d", a.amount)
   557				}
   558			}
   559			return reg + extshift + amount
   560	
   561		case MemImmediate:
   562			off := ""
   563			base := ""
   564			regno := uint16(a.Base) & 31
   565			if regno == 31 {
   566				base = "(RSP)"
   567			} else {
   568				base = fmt.Sprintf("(R%d)", regno)
   569			}
   570			if a.imm != 0 && a.Mode != AddrPostReg {
   571				off = fmt.Sprintf("%d", a.imm)
   572			} else if a.Mode == AddrPostReg {
   573				postR := fmt.Sprintf("(R%d)", a.imm)
   574				return base + postR
   575			}
   576			return off + base
   577	
   578		case MemExtend:
   579			base := ""
   580			index := ""
   581			indexreg := ""
   582			regno := uint16(a.Base) & 31
   583			if regno == 31 {
   584				base = "(RSP)"
   585			} else {
   586				base = fmt.Sprintf("(R%d)", regno)
   587			}
   588			regno = uint16(a.Index) & 31
   589			if regno == 31 {
   590				indexreg = "ZR"
   591			} else {
   592				indexreg = fmt.Sprintf("R%d", regno)
   593			}
   594	
   595			if a.Extend == lsl {
   596				// a.Amount indicates the index shift amount, encoded in "S" field.
   597				// a.ShiftMustBeZero is set true when the index shift amount must be 0,
   598				// even if the a.Amount field is not 0.
   599				// When a.ShiftMustBeZero is ture, GNU syntax prints #0 shift amount if
   600				// "S" equals to 1, or does not print #0 shift amount if "S" equals to 0.
   601				// Go syntax should never print a zero index shift amount.
   602				if a.Amount != 0 && !a.ShiftMustBeZero {
   603					index = fmt.Sprintf("(%s<<%d)", indexreg, a.Amount)
   604				} else {
   605					index = fmt.Sprintf("(%s)", indexreg)
   606				}
   607			} else {
   608				if a.Amount != 0 && !a.ShiftMustBeZero {
   609					index = fmt.Sprintf("(%s.%s<<%d)", indexreg, a.Extend.String(), a.Amount)
   610				} else {
   611					index = fmt.Sprintf("(%s.%s)", indexreg, a.Extend.String())
   612				}
   613			}
   614	
   615			return base + index
   616	
   617		case Cond:
   618			switch arg.String() {
   619			case "CS":
   620				return "HS"
   621			case "CC":
   622				return "LO"
   623			}
   624	
   625		case Imm_clrex:
   626			return fmt.Sprintf("$%d", uint32(a))
   627	
   628		case Imm_dcps:
   629			return fmt.Sprintf("$%d", uint32(a))
   630	
   631		case Imm_option:
   632			return fmt.Sprintf("$%d", uint8(a))
   633	
   634		case Imm_hint:
   635			return fmt.Sprintf("$%d", uint8(a))
   636	
   637		case Imm_fp:
   638			var s, pre, numerator, denominator int16
   639			var result float64
   640			if a.s == 0 {
   641				s = 1
   642			} else {
   643				s = -1
   644			}
   645			pre = s * int16(16+a.pre)
   646			if a.exp > 0 {
   647				numerator = (pre << uint8(a.exp))
   648				denominator = 16
   649			} else {
   650				numerator = pre
   651				denominator = (16 << uint8(-1*a.exp))
   652			}
   653			result = float64(numerator) / float64(denominator)
   654			return strings.TrimRight(fmt.Sprintf("$%f", result), "0")
   655	
   656		case RegisterWithArrangement:
   657			result := a.r.String()
   658			arrange := a.a.String()
   659			c := []rune(arrange)
   660			switch len(c) {
   661			case 3:
   662				c[1], c[2] = c[2], c[1] // .8B -> .B8
   663			case 4:
   664				c[1], c[2], c[3] = c[3], c[1], c[2] // 16B -> B16
   665			}
   666			arrange = string(c)
   667			result += arrange
   668			if a.cnt > 0 {
   669				result = "[" + result
   670				for i := 1; i < int(a.cnt); i++ {
   671					cur := V0 + Reg((uint16(a.r)-uint16(V0)+uint16(i))&31)
   672					result += ", " + cur.String() + arrange
   673				}
   674				result += "]"
   675			}
   676			return result
   677	
   678		case RegisterWithArrangementAndIndex:
   679			result := a.r.String()
   680			arrange := a.a.String()
   681			result += arrange
   682			if a.cnt > 1 {
   683				result = "[" + result
   684				for i := 1; i < int(a.cnt); i++ {
   685					cur := V0 + Reg((uint16(a.r)-uint16(V0)+uint16(i))&31)
   686					result += ", " + cur.String() + arrange
   687				}
   688				result += "]"
   689			}
   690			return fmt.Sprintf("%s[%d]", result, a.index)
   691	
   692		case Systemreg:
   693			return fmt.Sprintf("$%d", uint32(a.op0&1)<<14|uint32(a.op1&7)<<11|uint32(a.cn&15)<<7|uint32(a.cm&15)<<3|uint32(a.op2)&7)
   694	
   695		case Imm_prfop:
   696			if strings.Contains(a.String(), "#") {
   697				return fmt.Sprintf("$%d", a)
   698			}
   699		}
   700	
   701		return strings.ToUpper(arg.String())
   702	}
   703	

View as plain text