func (p *Parser) operand(a *obj.Addr) {
	//fmt.Printf("Operand: %v\n", p.input)
	if len(p.input) == 0 {
		p.errorf("empty operand: cannot happen")
		return
	}
	// General address (with a few exceptions) looks like
	//	$sym±offset(SB)(reg)(index*scale)
	// Exceptions are:
	//
	//	R1
	//	offset
	//	$offset
	// Every piece is optional, so we scan left to right and what
	// we discover tells us where we are.

	// Prefix: $.
	var prefix rune
	switch tok := p.peek(); tok {
	case '$', '*':
		prefix = rune(tok)
		p.next()
	}

	// Symbol: sym±offset(SB)
	tok := p.next()
	name := tok.String()
	if tok.ScanToken == scanner.Ident && !p.atStartOfRegister(name) {
		switch p.arch.Family {
		case sys.ARM64:
			// arm64 special operands.
			if opd := arch.GetARM64SpecialOperand(name); opd != arm64.SPOP_END {
				a.Type = obj.TYPE_SPECIAL
				a.Offset = int64(opd)
				break
			}
			fallthrough
		default:
			// We have a symbol. Parse $sym±offset(symkind)
			p.symbolReference(a, name, prefix)
		}
		// fmt.Printf("SYM %s\n", obj.Dconv(&emptyProg, 0, a))
		if p.peek() == scanner.EOF {
			return
		}
	}

	// Special register list syntax for arm: [R1,R3-R7]
	if tok.ScanToken == '[' {
		if prefix != 0 {
			p.errorf("illegal use of register list")
		}
		p.registerList(a)
		p.expectOperandEnd()
		return
	}

	// Register: R1
	if tok.ScanToken == scanner.Ident && p.atStartOfRegister(name) {
		if p.atRegisterShift() {
			// ARM shifted register such as R1<<R2 or R1>>2.
			a.Type = obj.TYPE_SHIFT
			a.Offset = p.registerShift(tok.String(), prefix)
			if p.peek() == '(' {
				// Can only be a literal register here.
				p.next()
				tok := p.next()
				name := tok.String()
				if !p.atStartOfRegister(name) {
					p.errorf("expected register; found %s", name)
				}
				a.Reg, _ = p.registerReference(name)
				p.get(')')
			}
		} else if p.atRegisterExtension() {
			a.Type = obj.TYPE_REG
			p.registerExtension(a, tok.String(), prefix)
			p.expectOperandEnd()
			return
		} else if r1, r2, scale, ok := p.register(tok.String(), prefix); ok {
			if scale != 0 {
				p.errorf("expected simple register reference")
			}
			a.Type = obj.TYPE_REG
			a.Reg = r1
			if r2 != 0 {
				// Form is R1:R2. It is on RHS and the second register
				// needs to go into the LHS.
				panic("cannot happen (Addr.Reg2)")
			}
		}
		// fmt.Printf("REG %s\n", obj.Dconv(&emptyProg, 0, a))
		p.expectOperandEnd()
		return
	}

	// Constant.
	haveConstant := false
	switch tok.ScanToken {
	case scanner.Int, scanner.Float, scanner.String, scanner.Char, '+', '-', '~':
		haveConstant = true
	case '(':
		// Could be parenthesized expression or (R). Must be something, though.
		tok := p.next()
		if tok.ScanToken == scanner.EOF {
			p.errorf("missing right parenthesis")
			return
		}
		rname := tok.String()
		p.back()
		haveConstant = !p.atStartOfRegister(rname)
		if !haveConstant {
			p.back() // Put back the '('.
		}
	}
	if haveConstant {
		p.back()
		if p.have(scanner.Float) {
			if prefix != '$' {
				p.errorf("floating-point constant must be an immediate")
			}
			a.Type = obj.TYPE_FCONST
			a.Val = p.floatExpr()
			// fmt.Printf("FCONST %s\n", obj.Dconv(&emptyProg, 0, a))
			p.expectOperandEnd()
			return
		}
		if p.have(scanner.String) {
			if prefix != '$' {
				p.errorf("string constant must be an immediate")
				return
			}
			str, err := strconv.Unquote(p.get(scanner.String).String())
			if err != nil {
				p.errorf("string parse error: %s", err)
			}
			a.Type = obj.TYPE_SCONST
			a.Val = str
			// fmt.Printf("SCONST %s\n", obj.Dconv(&emptyProg, 0, a))
			p.expectOperandEnd()
			return
		}
		a.Offset = int64(p.expr())
		if p.peek() != '(' {
			switch prefix {
			case '$':
				a.Type = obj.TYPE_CONST
			case '*':
				a.Type = obj.TYPE_INDIR // Can appear but is illegal, will be rejected by the linker.
			default:
				a.Type = obj.TYPE_MEM
			}
			// fmt.Printf("CONST %d %s\n", a.Offset, obj.Dconv(&emptyProg, 0, a))
			p.expectOperandEnd()
			return
		}
		// fmt.Printf("offset %d \n", a.Offset)
	}

	// Register indirection: (reg) or (index*scale). We are on the opening paren.
	p.registerIndirect(a, prefix)
	// fmt.Printf("DONE %s\n", p.arch.Dconv(&emptyProg, 0, a))

	p.expectOperandEnd()
	return
}
// operand parses a general operand and stores the result in *a.
operand parses a general operand and stores the result in *a.
// operand parses a general operand and stores the result in * a .
func (p *Parser) operand(a *obj.Addr) {
	if len(p.input) == 0 {
		p.errorf("empty operand: cannot happen")
		return
	}
		R1
		offset
		$offset
	 Every piece is optional, so we scan left to right and what
	 we discover tells us where we are.
	 Prefix: $.
	var prefix rune
	switch tok := p.peek(); tok {
	case '$', '*':
		prefix = rune(tok)
		p.next()
	}
	 Symbol: sym±offset(SB)
	tok := p.next()
	name := tok.String()
	if tok.ScanToken == scanner.Ident && !p.atStartOfRegister(name) {
		switch p.arch.Family {
		case sys.ARM64:
			 arm64 special operands.
			if opd := arch.GetARM64SpecialOperand(name); opd != arm64.SPOP_END {
				a.Type = obj.TYPE_SPECIAL
				a.Offset = int64(opd)
				break
			}
			fallthrough
		default:
			 We have a symbol. Parse $sym±offset(symkind)
			p.symbolReference(a, name, prefix)
		}
		 fmt.Printf("SYM %s\n", obj.Dconv(&emptyProg, 0, a))
		if p.peek() == scanner.EOF {
			return
		}
	}
	 Special register list syntax for arm: [R1,R3-R7]
	if tok.ScanToken == '[' {
		if prefix != 0 {
			p.errorf("illegal use of register list")
		}
		p.registerList(a)
		p.expectOperandEnd()
		return
	}
	 Register: R1
	if tok.ScanToken == scanner.Ident && p.atStartOfRegister(name) {
		if p.atRegisterShift() {
			 ARM shifted register such as R1<<R2 or R1>>2.
			a.Type = obj.TYPE_SHIFT
			a.Offset = p.registerShift(tok.String(), prefix)
			if p.peek() == '(' {
				 Can only be a literal register here.
				p.next()
				tok := p.next()
				name := tok.String()
				if !p.atStartOfRegister(name) {
					p.errorf("expected register; found %s", name)
				}
				a.Reg, _ = p.registerReference(name)
				p.get(')')
			}
		} else if p.atRegisterExtension() {
			a.Type = obj.TYPE_REG
			p.registerExtension(a, tok.String(), prefix)
			p.expectOperandEnd()
			return
		} else if r1, r2, scale, ok := p.register(tok.String(), prefix); ok {
			if scale != 0 {
				p.errorf("expected simple register reference")
			}
			a.Type = obj.TYPE_REG
			a.Reg = r1
			if r2 != 0 {
				 Form is R1:R2. It is on RHS and the second register
				 needs to go into the LHS.
				panic("cannot happen (Addr.Reg2)")
			}
		}
		 fmt.Printf("REG %s\n", obj.Dconv(&emptyProg, 0, a))
		p.expectOperandEnd()
		return
	}
	 Constant.
	haveConstant := false
	switch tok.ScanToken {
	case scanner.Int, scanner.Float, scanner.String, scanner.Char, '+', '-', '~':
		haveConstant = true
	case '(':
		 Could be parenthesized expression or (R). Must be something, though.
		tok := p.next()
		if tok.ScanToken == scanner.EOF {
			p.errorf("missing right parenthesis")
			return
		}
		rname := tok.String()
		p.back()
		haveConstant = !p.atStartOfRegister(rname)
		if !haveConstant {
			p.back()  Put back the '('.
		}
	}
	if haveConstant {
		p.back()
		if p.have(scanner.Float) {
			if prefix != '$' {
				p.errorf("floating-point constant must be an immediate")
			}
			a.Type = obj.TYPE_FCONST
			a.Val = p.floatExpr()
			 fmt.Printf("FCONST %s\n", obj.Dconv(&emptyProg, 0, a))
			p.expectOperandEnd()
			return
		}
		if p.have(scanner.String) {
			if prefix != '$' {
				p.errorf("string constant must be an immediate")
				return
			}
			str, err := strconv.Unquote(p.get(scanner.String).String())
			if err != nil {
				p.errorf("string parse error: %s", err)
			}
			a.Type = obj.TYPE_SCONST
			a.Val = str
			 fmt.Printf("SCONST %s\n", obj.Dconv(&emptyProg, 0, a))
			p.expectOperandEnd()
			return
		}
		a.Offset = int64(p.expr())
		if p.peek() != '(' {
			switch prefix {
			case '$':
				a.Type = obj.TYPE_CONST
			case '*':
				a.Type = obj.TYPE_INDIR  Can appear but is illegal, will be rejected by the linker.
			default:
				a.Type = obj.TYPE_MEM
			}
			 fmt.Printf("CONST %d %s\n", a.Offset, obj.Dconv(&emptyProg, 0, a))
			p.expectOperandEnd()
			return
		}
		 fmt.Printf("offset %d \n", a.Offset)
	}
	 Register indirection: (reg) or (index*scale). We are on the opening paren.
	p.registerIndirect(a, prefix)
	 fmt.Printf("DONE %s\n", p.arch.Dconv(&emptyProg, 0, a))
	p.expectOperandEnd()
	return
}
func ( p * Parser ) operand ( a * obj . Addr ) { if len ( p . input ) == 0 { p . errorf ( " " ) return } var prefix rune switch tok := p . peek ( ) ; tok { case '$' , '*' : prefix = rune ( tok ) p . next ( ) } tok := p . next ( ) name := tok . String ( ) if tok . ScanToken == scanner . Ident && ! p . atStartOfRegister ( name ) { switch p . arch . Family { case sys . ARM64 : if opd := arch . GetARM64SpecialOperand ( name ) ; opd != arm64 . SPOP_END { a . Type = obj . TYPE_SPECIAL a . Offset = int64 ( opd ) break } fallthrough default : p . symbolReference ( a , name , prefix ) } if p . peek ( ) == scanner . EOF { return } } if tok . ScanToken == '[' { if prefix != 0 { p . errorf ( " " ) } p . registerList ( a ) p . expectOperandEnd ( ) return } if tok . ScanToken == scanner . Ident && p . atStartOfRegister ( name ) { if p . atRegisterShift ( ) { a . Type = obj . TYPE_SHIFT a . Offset = p . registerShift ( tok . String ( ) , prefix ) if p . peek ( ) == '(' { p . next ( ) tok := p . next ( ) name := tok . String ( ) if ! p . atStartOfRegister ( name ) { p . errorf ( " " , name ) } a . Reg , _ = p . registerReference ( name ) p . get ( ')' ) } } else if p . atRegisterExtension ( ) { a . Type = obj . TYPE_REG p . registerExtension ( a , tok . String ( ) , prefix ) p . expectOperandEnd ( ) return } else if r1 , r2 , scale , ok := p . register ( tok . String ( ) , prefix ) ; ok { if scale != 0 { p . errorf ( " " ) } a . Type = obj . TYPE_REG a . Reg = r1 if r2 != 0 { panic ( " " ) } } p . expectOperandEnd ( ) return } haveConstant := false switch tok . ScanToken { case scanner . Int , scanner . Float , scanner . String , scanner . Char , '+' , '-' , '~' : haveConstant = true case '(' : tok := p . next ( ) if tok . ScanToken == scanner . EOF { p . errorf ( " " ) return } rname := tok . String ( ) p . back ( ) haveConstant = ! p . atStartOfRegister ( rname ) if ! haveConstant { p . back ( ) } } if haveConstant { p . back ( ) if p . have ( scanner . Float ) { if prefix != '$' { p . errorf ( " " ) } a . Type = obj . TYPE_FCONST a . Val = p . floatExpr ( ) p . expectOperandEnd ( ) return } if p . have ( scanner . String ) { if prefix != '$' { p . errorf ( " " ) return } str , err := strconv . Unquote ( p . get ( scanner . String ) . String ( ) ) if err != nil { p . errorf ( " " , err ) } a . Type = obj . TYPE_SCONST a . Val = str p . expectOperandEnd ( ) return } a . Offset = int64 ( p . expr ( ) ) if p . peek ( ) != '(' { switch prefix { case '$' : a . Type = obj . TYPE_CONST case '*' : a . Type = obj . TYPE_INDIR default : a . Type = obj . TYPE_MEM } p . expectOperandEnd ( ) return } } p . registerIndirect ( a , prefix ) p . expectOperandEnd ( ) return }
operand parses a general operand and stores the result in *a.
operand parses a general operand and stores the result in * a .
//fmt.Printf("Operand: %v\n", p.input) // General address (with a few exceptions) looks like //	$sym±offset(SB)(reg)(index*scale) // Exceptions are: // //	R1 //	offset //	$offset // Every piece is optional, so we scan left to right and what // we discover tells us where we are. // Prefix: $. // Symbol: sym±offset(SB) // arm64 special operands. // We have a symbol. Parse $sym±offset(symkind) // fmt.Printf("SYM %s\n", obj.Dconv(&emptyProg, 0, a)) // Special register list syntax for arm: [R1,R3-R7] // Register: R1 // ARM shifted register such as R1<<R2 or R1>>2. // Can only be a literal register here. // Form is R1:R2. It is on RHS and the second register // needs to go into the LHS. // fmt.Printf("REG %s\n", obj.Dconv(&emptyProg, 0, a)) // Constant. // Could be parenthesized expression or (R). Must be something, though. // Put back the '('. // fmt.Printf("FCONST %s\n", obj.Dconv(&emptyProg, 0, a)) // fmt.Printf("SCONST %s\n", obj.Dconv(&emptyProg, 0, a)) // Can appear but is illegal, will be rejected by the linker. // fmt.Printf("CONST %d %s\n", a.Offset, obj.Dconv(&emptyProg, 0, a)) // fmt.Printf("offset %d \n", a.Offset) // Register indirection: (reg) or (index*scale). We are on the opening paren. // fmt.Printf("DONE %s\n", p.arch.Dconv(&emptyProg, 0, a))