コード例 #1
0
// symbolReference parses a symbol that is known not to be a register.
func (p *Parser) symbolReference(a *obj.Addr, name string, prefix rune) {
	// Identifier is a name.
	switch prefix {
	case 0:
		a.Type = obj.TYPE_MEM
	case '$':
		a.Type = obj.TYPE_ADDR
	case '*':
		a.Type = obj.TYPE_INDIR
	}
	// Weirdness with statics: Might now have "<>".
	isStatic := 0 // TODO: Really a boolean, but Linklookup wants a "version" integer.
	if p.peek() == '<' {
		isStatic = 1
		p.next()
		p.get('>')
	}
	if p.peek() == '+' || p.peek() == '-' {
		a.Offset = int64(p.expr())
	}
	a.Sym = obj.Linklookup(p.ctxt, name, isStatic)
	if p.peek() == scanner.EOF {
		if prefix != 0 {
			p.errorf("illegal addressing mode for symbol %s", name)
		}
		return
	}
	// Expect (SB) or (FP), (PC), (SB), or (SP)
	p.get('(')
	reg := p.get(scanner.Ident).String()
	p.get(')')
	p.setPseudoRegister(a, reg, isStatic != 0, prefix)
}
コード例 #2
0
// setPseudoRegister sets the NAME field of addr for a pseudo-register reference such as (SB).
func (p *Parser) setPseudoRegister(addr *obj.Addr, reg string, isStatic bool, prefix rune) {
	if addr.Reg != 0 {
		p.errorf("internal error: reg %s already set in pseudo", reg)
	}
	switch reg {
	case "FP":
		addr.Name = obj.NAME_PARAM
	case "PC":
		if prefix != 0 {
			p.errorf("illegal addressing mode for PC")
		}
		addr.Type = obj.TYPE_BRANCH // We set the type and leave NAME untouched. See asmJump.
	case "SB":
		addr.Name = obj.NAME_EXTERN
		if isStatic {
			addr.Name = obj.NAME_STATIC
		}
	case "SP":
		addr.Name = obj.NAME_AUTO // The pseudo-stack.
	default:
		p.errorf("expected pseudo-register; found %s", reg)
	}
	if prefix == '$' {
		addr.Type = obj.TYPE_ADDR
	}
}
コード例 #3
0
ファイル: obj6.go プロジェクト: achanda/go
func indir_cx(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
	if ctxt.Headtype == obj.Hnacl && p.Mode == 64 {
		a.Type = obj.TYPE_MEM
		a.Reg = REG_R15
		a.Index = REG_CX
		a.Scale = 1
		return
	}

	a.Type = obj.TYPE_MEM
	a.Reg = REG_CX
}
コード例 #4
0
ファイル: parse.go プロジェクト: josharian/go.ssa
// registerList parses an ARM register list expression, a list of registers in [].
// There may be comma-separated ranges or individual registers, as in
// [R1,R3-R5]. Only R0 through R15 may appear.
// The opening bracket has been consumed.
func (p *Parser) registerList(a *obj.Addr) {
	// One range per loop.
	var bits uint16
	for {
		tok := p.next()
		if tok.ScanToken == ']' {
			break
		}
		lo := p.registerNumber(tok.String())
		hi := lo
		if p.peek() == '-' {
			p.next()
			hi = p.registerNumber(p.next().String())
		}
		if hi < lo {
			lo, hi = hi, lo
		}
		for lo <= hi {
			if bits&(1<<lo) != 0 {
				p.errorf("register R%d already in list", lo)
			}
			bits |= 1 << lo
			lo++
		}
		if p.peek() != ']' {
			p.get(',')
		}
	}
	a.Type = obj.TYPE_REGLIST
	a.Offset = int64(bits)
}
コード例 #5
0
ファイル: obj.go プロジェクト: kuangchanglang/go
func datagostring(sval string, a *obj.Addr) {
	symhdr, _ := stringsym(sval)
	a.Type = obj.TYPE_MEM
	a.Name = obj.NAME_EXTERN
	a.Sym = symhdr
	a.Offset = 0
}
コード例 #6
0
ファイル: ssa.go プロジェクト: hurkgu/go
// scratchFpMem initializes an Addr (field of a Prog)
// to reference the scratchpad memory for movement between
// F and G registers for FP conversions.
func scratchFpMem(s *gc.SSAGenState, a *obj.Addr) {
	a.Type = obj.TYPE_MEM
	a.Name = obj.NAME_AUTO
	a.Node = s.ScratchFpMem
	a.Sym = gc.Linksym(s.ScratchFpMem.Sym)
	a.Reg = ppc64.REGSP
}
コード例 #7
0
ファイル: obj.go プロジェクト: duhaibo0404/go-1
func Datastring(s string, a *obj.Addr) {
	_, symdata := stringsym(s)
	a.Type = obj.TYPE_MEM
	a.Name = obj.NAME_EXTERN
	a.Sym = symdata
	a.Offset = 0
	a.Etype = uint8(Simtype[TINT])
}
コード例 #8
0
ファイル: obj.go プロジェクト: Ericean/go
func Datastring(s string, a *obj.Addr) {
	sym := stringsym(s)
	a.Type = obj.TYPE_MEM
	a.Name = obj.NAME_EXTERN
	a.Sym = Linksym(sym)
	a.Node = sym.Def
	a.Offset = int64(Widthptr) + int64(Widthint) // skip header
	a.Etype = Simtype[TINT]
}
コード例 #9
0
ファイル: obj.go プロジェクト: ronaldslc/go
func datagostring(sval string, a *obj.Addr) {
	symhdr, _ := stringsym(sval)
	a.Type = obj.TYPE_MEM
	a.Name = obj.NAME_EXTERN
	a.Sym = Linksym(symhdr)
	a.Node = symhdr.Def
	a.Offset = 0
	a.Etype = TSTRING
}
コード例 #10
0
ファイル: obj.go プロジェクト: ronaldslc/go
func Datastring(s string, a *obj.Addr) {
	_, symdata := stringsym(s)
	a.Type = obj.TYPE_MEM
	a.Name = obj.NAME_EXTERN
	a.Sym = Linksym(symdata)
	a.Node = symdata.Def
	a.Offset = 0
	a.Etype = Simtype[TINT]
}
コード例 #11
0
ファイル: reg.go プロジェクト: danny8002/go
func addreg(a *obj.Addr, rn int) {
	a.Sym = nil
	a.Node = nil
	a.Offset = 0
	a.Type = obj.TYPE_REG
	a.Reg = int16(rn)
	a.Name = 0

	Ostats.Ncvtreg++
}
コード例 #12
0
ファイル: gsubr.go プロジェクト: kuangchanglang/go
// Naddr rewrites a to refer to n.
// It assumes that a is zeroed on entry.
func Naddr(a *obj.Addr, n *Node) {
	if n == nil {
		return
	}

	if n.Op != ONAME {
		Debug['h'] = 1
		Dump("naddr", n)
		Fatalf("naddr: bad %v %v", n.Op, Ctxt.Dconv(a))
	}

	a.Offset = n.Xoffset
	s := n.Sym
	a.Node = n.Orig

	if s == nil {
		Fatalf("naddr: nil sym %v", n)
	}
	if n.Name.Method && n.Type != nil && n.Type.Sym != nil && n.Type.Sym.Pkg != nil {
		Fatalf("naddr: weird method %v", n)
	}

	a.Type = obj.TYPE_MEM
	switch n.Class {
	default:
		Fatalf("naddr: ONAME class %v %d\n", n.Sym, n.Class)

	case PEXTERN, PFUNC:
		a.Name = obj.NAME_EXTERN

	case PAUTO:
		a.Name = obj.NAME_AUTO

	case PPARAM, PPARAMOUT:
		a.Name = obj.NAME_PARAM
	}

	a.Sym = Linksym(s)
}
コード例 #13
0
ファイル: parse.go プロジェクト: sreis/go
// registerList parses an ARM register list expression, a list of registers in [].
// There may be comma-separated ranges or individual registers, as in
// [R1,R3-R5]. Only R0 through R15 may appear.
// The opening bracket has been consumed.
func (p *Parser) registerList(a *obj.Addr) {
	// One range per loop.
	const maxReg = 16
	var bits uint16
ListLoop:
	for {
		tok := p.next()
		switch tok.ScanToken {
		case ']':
			break ListLoop
		case scanner.EOF:
			p.errorf("missing ']' in register list")
			return
		}
		// Parse the upper and lower bounds.
		lo := p.registerNumber(tok.String())
		hi := lo
		if p.peek() == '-' {
			p.next()
			hi = p.registerNumber(p.next().String())
		}
		if hi < lo {
			lo, hi = hi, lo
		}
		// Check there are no duplicates in the register list.
		for i := 0; lo <= hi && i < maxReg; i++ {
			if bits&(1<<lo) != 0 {
				p.errorf("register R%d already in list", lo)
			}
			bits |= 1 << lo
			lo++
		}
		if p.peek() != ']' {
			p.get(',')
		}
	}
	a.Type = obj.TYPE_REGLIST
	a.Offset = int64(bits)
}
コード例 #14
0
// registerList parses an ARM register list expression, a list of registers in [].
// There may be comma-separated ranges or individual registers, as in
// [R1,R3-R5]. Only R0 through R15 may appear.
// The opening bracket has been consumed.
func (p *Parser) registerList(a *obj.Addr) {
	// One range per loop.
	var bits uint16
ListLoop:
	for {
		tok := p.next()
		switch tok.ScanToken {
		case ']':
			break ListLoop
		case scanner.EOF:
			p.errorf("missing ']' in register list")
			return
		}
		lo := p.registerNumber(tok.String())
		hi := lo
		if p.peek() == '-' {
			p.next()
			hi = p.registerNumber(p.next().String())
		}
		if hi < lo {
			lo, hi = hi, lo
		}
		for lo <= hi {
			if bits&(1<<lo) != 0 {
				p.errorf("register R%d already in list", lo)
			}
			bits |= 1 << lo
			lo++
		}
		if p.peek() != ']' {
			p.get(',')
		}
	}
	a.Type = obj.TYPE_REGLIST
	a.Offset = int64(bits)
}
コード例 #15
0
ファイル: reg.go プロジェクト: danny8002/go
func mkvar(f *Flow, a *obj.Addr) Bits {
	// mark registers used
	if a.Type == obj.TYPE_NONE {
		return zbits
	}

	r := f.Data.(*Reg)
	r.use1.b[0] |= Thearch.Doregbits(int(a.Index)) // TODO: Use RtoB

	var n int
	switch a.Type {
	default:
		regu := Thearch.Doregbits(int(a.Reg)) | Thearch.RtoB(int(a.Reg)) // TODO: Use RtoB
		if regu == 0 {
			return zbits
		}
		bit := zbits
		bit.b[0] = regu
		return bit

		// TODO(rsc): Remove special case here.
	case obj.TYPE_ADDR:
		var bit Bits
		if Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
			goto memcase
		}
		a.Type = obj.TYPE_MEM
		bit = mkvar(f, a)
		setaddrs(bit)
		a.Type = obj.TYPE_ADDR
		Ostats.Naddr++
		return zbits

	memcase:
		fallthrough

	case obj.TYPE_MEM:
		if r != nil {
			r.use1.b[0] |= Thearch.RtoB(int(a.Reg))
		}

		/* NOTE: 5g did
		if(r->f.prog->scond & (C_PBIT|C_WBIT))
			r->set.b[0] |= RtoB(a->reg);
		*/
		switch a.Name {
		default:
			// Note: This case handles NAME_EXTERN and NAME_STATIC.
			// We treat these as requiring eager writes to memory, due to
			// the possibility of a fault handler looking at them, so there is
			// not much point in registerizing the loads.
			// If we later choose the set of candidate variables from a
			// larger list, these cases could be deprioritized instead of
			// removed entirely.
			return zbits

		case obj.NAME_PARAM,
			obj.NAME_AUTO:
			n = int(a.Name)
		}
	}

	node, _ := a.Node.(*Node)
	if node == nil || node.Op != ONAME || node.Orig == nil {
		return zbits
	}
	node = node.Orig
	if node.Orig != node {
		Fatalf("%v: bad node", Ctxt.Dconv(a))
	}
	if node.Sym == nil || node.Sym.Name[0] == '.' {
		return zbits
	}
	et := EType(a.Etype)
	o := a.Offset
	w := a.Width
	if w < 0 {
		Fatalf("bad width %d for %v", w, Ctxt.Dconv(a))
	}

	flag := 0
	var v *Var
	for i := 0; i < nvar; i++ {
		v = &vars[i]
		if v.node == node && int(v.name) == n {
			if v.offset == o {
				if v.etype == et {
					if int64(v.width) == w {
						// TODO(rsc): Remove special case for arm here.
						if flag == 0 || Thearch.Thechar != '5' {
							return blsh(uint(i))
						}
					}
				}
			}

			// if they overlap, disable both
			if overlap_reg(v.offset, v.width, o, int(w)) {
				//				print("disable overlap %s %d %d %d %d, %E != %E\n", s->name, v->offset, v->width, o, w, v->etype, et);
				v.addr = 1

				flag = 1
			}
		}
	}

	switch et {
	case 0, TFUNC:
		return zbits
	}

	if nvar >= NVAR {
		if Debug['w'] > 1 && node != nil {
			Fatalf("variable not optimized: %v", Nconv(node, obj.FmtSharp))
		}
		if Debug['v'] > 0 {
			Warn("variable not optimized: %v", Nconv(node, obj.FmtSharp))
		}

		// If we're not tracking a word in a variable, mark the rest as
		// having its address taken, so that we keep the whole thing
		// live at all calls. otherwise we might optimize away part of
		// a variable but not all of it.
		var v *Var
		for i := 0; i < nvar; i++ {
			v = &vars[i]
			if v.node == node {
				v.addr = 1
			}
		}

		return zbits
	}

	i := nvar
	nvar++
	v = &vars[i]
	v.id = i
	v.offset = o
	v.name = int8(n)
	v.etype = et
	v.width = int(w)
	v.addr = int8(flag) // funny punning
	v.node = node

	// node->opt is the head of a linked list
	// of Vars within the given Node, so that
	// we can start at a Var and find all the other
	// Vars in the same Go variable.
	v.nextinnode, _ = node.Opt().(*Var)

	node.SetOpt(v)

	bit := blsh(uint(i))
	if n == obj.NAME_EXTERN || n == obj.NAME_STATIC {
		for z := 0; z < BITS; z++ {
			externs.b[z] |= bit.b[z]
		}
	}
	if n == obj.NAME_PARAM {
		for z := 0; z < BITS; z++ {
			params.b[z] |= bit.b[z]
		}
	}

	if node.Class == PPARAM {
		for z := 0; z < BITS; z++ {
			ivar.b[z] |= bit.b[z]
		}
	}
	if node.Class == PPARAMOUT {
		for z := 0; z < BITS; z++ {
			ovar.b[z] |= bit.b[z]
		}
	}

	// Treat values with their address taken as live at calls,
	// because the garbage collector's liveness analysis in plive.go does.
	// These must be consistent or else we will elide stores and the garbage
	// collector will see uninitialized data.
	// The typical case where our own analysis is out of sync is when the
	// node appears to have its address taken but that code doesn't actually
	// get generated and therefore doesn't show up as an address being
	// taken when we analyze the instruction stream.
	// One instance of this case is when a closure uses the same name as
	// an outer variable for one of its own variables declared with :=.
	// The parser flags the outer variable as possibly shared, and therefore
	// sets addrtaken, even though it ends up not being actually shared.
	// If we were better about _ elision, _ = &x would suffice too.
	// The broader := in a closure problem is mentioned in a comment in
	// closure.go:/^typecheckclosure and dcl.go:/^oldname.
	if node.Addrtaken {
		v.addr = 1
	}

	// Disable registerization for globals, because:
	// (1) we might panic at any time and we want the recovery code
	// to see the latest values (issue 1304).
	// (2) we don't know what pointers might point at them and we want
	// loads via those pointers to see updated values and vice versa (issue 7995).
	//
	// Disable registerization for results if using defer, because the deferred func
	// might recover and return, causing the current values to be used.
	if node.Class == PEXTERN || (hasdefer && node.Class == PPARAMOUT) {
		v.addr = 1
	}

	if Debug['R'] != 0 {
		fmt.Printf("bit=%2d et=%v w=%d+%d %v %v flag=%d\n", i, Econv(et), o, w, Nconv(node, obj.FmtSharp), Ctxt.Dconv(a), v.addr)
	}
	Ostats.Nvar++

	return bit
}
コード例 #16
0
// registerIndirect parses the general form of a register indirection.
// It is can be (R1), (R2*scale), or (R1)(R2*scale) where R1 may be a simple
// register or register pair R:R or (R, R) or (R+R).
// Or it might be a pseudo-indirection like (FP).
// We are sitting on the opening parenthesis.
func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) {
	p.get('(')
	tok := p.next()
	name := tok.String()
	r1, r2, scale, ok := p.register(name, 0)
	if !ok {
		p.errorf("indirect through non-register %s", tok)
	}
	p.get(')')
	a.Type = obj.TYPE_MEM
	if r1 < 0 {
		// Pseudo-register reference.
		if r2 != 0 {
			p.errorf("cannot use pseudo-register in pair")
			return
		}
		// For SB, SP, and FP, there must be a name here. 0(FP) is not legal.
		if name != "PC" && a.Name == obj.NAME_NONE {
			p.errorf("cannot reference %s without a symbol", name)
		}
		p.setPseudoRegister(a, name, false, prefix)
		return
	}
	a.Reg = r1
	if r2 != 0 {
		// TODO: Consistency in the encoding would be nice here.
		if p.arch.Thechar == '5' || p.arch.Thechar == '7' {
			// Special form
			// ARM: destination register pair (R1, R2).
			// ARM64: register pair (R1, R2) for LDP/STP.
			if prefix != 0 || scale != 0 {
				p.errorf("illegal address mode for register pair")
				return
			}
			a.Type = obj.TYPE_REGREG
			a.Offset = int64(r2)
			// Nothing may follow
			return
		}
		if p.arch.Thechar == '9' {
			// Special form for PPC64: (R1+R2); alias for (R1)(R2*1).
			if prefix != 0 || scale != 0 {
				p.errorf("illegal address mode for register+register")
				return
			}
			a.Type = obj.TYPE_MEM
			a.Scale = 1
			a.Index = r2
			// Nothing may follow.
			return
		}
	}
	if r2 != 0 {
		p.errorf("indirect through register pair")
	}
	if prefix == '$' {
		a.Type = obj.TYPE_ADDR
	}
	if r1 == arch.RPC && prefix != 0 {
		p.errorf("illegal addressing mode for PC")
	}
	if scale == 0 && p.peek() == '(' {
		// General form (R)(R*scale).
		p.next()
		tok := p.next()
		r1, r2, scale, ok = p.register(tok.String(), 0)
		if !ok {
			p.errorf("indirect through non-register %s", tok)
		}
		if r2 != 0 {
			p.errorf("unimplemented two-register form")
		}
		a.Index = r1
		a.Scale = int16(scale)
		p.get(')')
	} else if scale != 0 {
		// First (R) was missing, all we have is (R*scale).
		a.Reg = 0
		a.Index = r1
		a.Scale = int16(scale)
	}
}
コード例 #17
0
ファイル: gsubr.go プロジェクト: wheelcomplex/go-1
/*
 * generate code to compute address of n,
 * a reference to a (perhaps nested) field inside
 * an array or struct.
 * return 0 on failure, 1 on success.
 * on success, leaves usable address in a.
 *
 * caller is responsible for calling sudoclean
 * after successful sudoaddable,
 * to release the register used for a.
 */
func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool {
	if n.Type == nil {
		return false
	}

	*a = obj.Addr{}

	switch n.Op {
	case gc.OLITERAL:
		if !gc.Isconst(n, gc.CTINT) {
			break
		}
		v := n.Int()
		if v >= 32000 || v <= -32000 {
			break
		}
		switch as {
		default:
			return false

		case x86.AADDB,
			x86.AADDW,
			x86.AADDL,
			x86.AADDQ,
			x86.ASUBB,
			x86.ASUBW,
			x86.ASUBL,
			x86.ASUBQ,
			x86.AANDB,
			x86.AANDW,
			x86.AANDL,
			x86.AANDQ,
			x86.AORB,
			x86.AORW,
			x86.AORL,
			x86.AORQ,
			x86.AXORB,
			x86.AXORW,
			x86.AXORL,
			x86.AXORQ,
			x86.AINCB,
			x86.AINCW,
			x86.AINCL,
			x86.AINCQ,
			x86.ADECB,
			x86.ADECW,
			x86.ADECL,
			x86.ADECQ,
			x86.AMOVB,
			x86.AMOVW,
			x86.AMOVL,
			x86.AMOVQ:
			break
		}

		cleani += 2
		reg := &clean[cleani-1]
		reg1 := &clean[cleani-2]
		reg.Op = gc.OEMPTY
		reg1.Op = gc.OEMPTY
		gc.Naddr(a, n)
		return true

	case gc.ODOT,
		gc.ODOTPTR:
		cleani += 2
		reg := &clean[cleani-1]
		reg1 := &clean[cleani-2]
		reg.Op = gc.OEMPTY
		reg1.Op = gc.OEMPTY
		var nn *gc.Node
		var oary [10]int64
		o := gc.Dotoffset(n, oary[:], &nn)
		if nn == nil {
			sudoclean()
			return false
		}

		if nn.Addable && o == 1 && oary[0] >= 0 {
			// directly addressable set of DOTs
			n1 := *nn

			n1.Type = n.Type
			n1.Xoffset += oary[0]
			gc.Naddr(a, &n1)
			return true
		}

		gc.Regalloc(reg, gc.Types[gc.Tptr], nil)
		n1 := *reg
		n1.Op = gc.OINDREG
		if oary[0] >= 0 {
			gc.Agen(nn, reg)
			n1.Xoffset = oary[0]
		} else {
			gc.Cgen(nn, reg)
			gc.Cgen_checknil(reg)
			n1.Xoffset = -(oary[0] + 1)
		}

		for i := 1; i < o; i++ {
			if oary[i] >= 0 {
				gc.Fatal("can't happen")
			}
			gins(movptr, &n1, reg)
			gc.Cgen_checknil(reg)
			n1.Xoffset = -(oary[i] + 1)
		}

		a.Type = obj.TYPE_NONE
		a.Index = obj.TYPE_NONE
		gc.Fixlargeoffset(&n1)
		gc.Naddr(a, &n1)
		return true

	case gc.OINDEX:
		return false
	}

	return false
}
コード例 #18
0
ファイル: y.go プロジェクト: bibbyflyaway/go
func (yyrcvr *yyParserImpl) Parse(yylex yyLexer) int {
	var yyn int
	var yylval yySymType
	var yyVAL yySymType
	var yyDollar []yySymType
	yyS := make([]yySymType, yyMaxDepth)

	Nerrs := 0   /* number of errors */
	Errflag := 0 /* error recovery flag */
	yystate := 0
	yychar := -1
	yytoken := -1 // yychar translated into internal numbering
	yyrcvr.lookahead = func() int { return yychar }
	defer func() {
		// Make sure we report no lookahead when not parsing.
		yychar = -1
		yytoken = -1
	}()
	yyp := -1
	goto yystack

ret0:
	return 0

ret1:
	return 1

yystack:
	/* put a state and value onto the stack */
	if yyDebug >= 4 {
		__yyfmt__.Printf("char %v in %v\n", yyTokname(yytoken), yyStatname(yystate))
	}

	yyp++
	if yyp >= len(yyS) {
		nyys := make([]yySymType, len(yyS)*2)
		copy(nyys, yyS)
		yyS = nyys
	}
	yyS[yyp] = yyVAL
	yyS[yyp].yys = yystate

yynewstate:
	yyn = yyPact[yystate]
	if yyn <= yyFlag {
		goto yydefault /* simple state */
	}
	if yychar < 0 {
		yychar, yytoken = yylex1(yylex, &yylval)
	}
	yyn += yytoken
	if yyn < 0 || yyn >= yyLast {
		goto yydefault
	}
	yyn = yyAct[yyn]
	if yyChk[yyn] == yytoken { /* valid shift */
		yychar = -1
		yytoken = -1
		yyVAL = yylval
		yystate = yyn
		if Errflag > 0 {
			Errflag--
		}
		goto yystack
	}

yydefault:
	/* default state action */
	yyn = yyDef[yystate]
	if yyn == -2 {
		if yychar < 0 {
			yychar, yytoken = yylex1(yylex, &yylval)
		}

		/* look through exception table */
		xi := 0
		for {
			if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
				break
			}
			xi += 2
		}
		for xi += 2; ; xi += 2 {
			yyn = yyExca[xi+0]
			if yyn < 0 || yyn == yytoken {
				break
			}
		}
		yyn = yyExca[xi+1]
		if yyn < 0 {
			goto ret0
		}
	}
	if yyn == 0 {
		/* error ... attempt to resume parsing */
		switch Errflag {
		case 0: /* brand new error */
			yylex.Error("syntax error")
			Nerrs++
			if yyDebug >= 1 {
				__yyfmt__.Printf("%s", yyStatname(yystate))
				__yyfmt__.Printf(" saw %s\n", yyTokname(yytoken))
			}
			fallthrough

		case 1, 2: /* incompletely recovered error ... try again */
			Errflag = 3

			/* find a state where "error" is a legal shift action */
			for yyp >= 0 {
				yyn = yyPact[yyS[yyp].yys] + yyErrCode
				if yyn >= 0 && yyn < yyLast {
					yystate = yyAct[yyn] /* simulate a shift of "error" */
					if yyChk[yystate] == yyErrCode {
						goto yystack
					}
				}

				/* the current p has no shift on "error", pop stack */
				if yyDebug >= 2 {
					__yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
				}
				yyp--
			}
			/* there is no state on the stack with an error shift ... abort */
			goto ret1

		case 3: /* no shift yet; clobber input char */
			if yyDebug >= 2 {
				__yyfmt__.Printf("error recovery discards %s\n", yyTokname(yytoken))
			}
			if yytoken == yyEofCode {
				goto ret1
			}
			yychar = -1
			yytoken = -1
			goto yynewstate /* try again in the same state */
		}
	}

	/* reduction by production yyn */
	if yyDebug >= 2 {
		__yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
	}

	yynt := yyn
	yypt := yyp
	_ = yypt // guard against "declared and not used"

	yyp -= yyR2[yyn]
	// yyp is now the index of $0. Perform the default action. Iff the
	// reduced production is ε, $1 is possibly out of range.
	if yyp+1 >= len(yyS) {
		nyys := make([]yySymType, len(yyS)*2)
		copy(nyys, yyS)
		yyS = nyys
	}
	yyVAL = yyS[yyp+1]

	/* consult goto table to find next state */
	yyn = yyR1[yyn]
	yyg := yyPgo[yyn]
	yyj := yyg + yyS[yyp].yys + 1

	if yyj >= yyLast {
		yystate = yyAct[yyg]
	} else {
		yystate = yyAct[yyj]
		if yyChk[yystate] != -yyn {
			yystate = yyAct[yyg]
		}
	}
	// dummy call; replaced with literal code
	switch yynt {

	case 2:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:72
		{
			stmtline = asm.Lineno
		}
	case 4:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:79
		{
			yyDollar[1].sym = asm.LabelLookup(yyDollar[1].sym)
			if yyDollar[1].sym.Type == LLAB && yyDollar[1].sym.Value != int64(asm.PC) {
				yyerror("redeclaration of %s", yyDollar[1].sym.Labelname)
			}
			yyDollar[1].sym.Type = LLAB
			yyDollar[1].sym.Value = int64(asm.PC)
		}
	case 6:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:89
		{
			yyDollar[1].sym.Type = LVAR
			yyDollar[1].sym.Value = yyDollar[3].lval
		}
	case 7:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:94
		{
			if yyDollar[1].sym.Value != yyDollar[3].lval {
				yyerror("redeclaration of %s", yyDollar[1].sym.Name)
			}
			yyDollar[1].sym.Value = yyDollar[3].lval
		}
	case 8:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:101
		{
			nosched = int(yyDollar[1].lval)
		}
	case 12:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:113
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 13:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:117
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 14:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:121
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 15:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:125
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 16:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:129
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 17:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:133
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 18:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:140
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 19:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:144
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 20:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:148
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 21:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:152
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 22:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:156
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 23:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:160
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 24:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:167
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 25:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:171
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 26:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:175
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 27:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:179
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 28:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:186
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 29:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:190
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 30:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:197
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 31:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:201
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 32:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:205
		{
			outgcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr, &yyDollar[6].addr)
		}
	case 33:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:209
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 34:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:213
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].lval), &nullgen)
		}
	case 35:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:220
		{
			outgcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr, &yyDollar[6].addr)
		}
	case 36:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:224
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 37:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:228
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 38:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:238
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].lval), &yyDollar[6].addr)
		}
	case 39:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:242
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].lval), &yyDollar[6].addr)
		}
	case 40:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:246
		{
			outgcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr, &yyDollar[6].addr)
		}
	case 41:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:250
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 42:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:254
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 43:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:258
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].lval), &yyDollar[6].addr)
		}
	case 44:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:262
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 45:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:266
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].lval), &yyDollar[6].addr)
		}
	case 46:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:270
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 47:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:274
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].lval), &yyDollar[6].addr)
		}
	case 48:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:278
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 49:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:282
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 50:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:286
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[2].addr)
		}
	case 51:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:293
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].lval), &yyDollar[6].addr)
		}
	case 52:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:300
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 53:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:304
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 54:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:311
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].addr.Reg), &yyDollar[4].addr)
		}
	case 55:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:315
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].lval), &yyDollar[6].addr)
		}
	case 56:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:323
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 57:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:327
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 58:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:331
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 59:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:335
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 60:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:339
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 61:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:343
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 62:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:347
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 63:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:351
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 64:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:360
		{
			outcode(int(yyDollar[1].lval), &nullgen, 0, &yyDollar[2].addr)
		}
	case 65:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:364
		{
			outcode(int(yyDollar[1].lval), &nullgen, 0, &yyDollar[2].addr)
		}
	case 66:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:368
		{
			outcode(int(yyDollar[1].lval), &nullgen, 0, &yyDollar[3].addr)
		}
	case 67:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:372
		{
			outcode(int(yyDollar[1].lval), &nullgen, 0, &yyDollar[3].addr)
		}
	case 68:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:376
		{
			outcode(int(yyDollar[1].lval), &nullgen, 0, &yyDollar[3].addr)
		}
	case 69:
		yyDollar = yyS[yypt-5 : yypt+1]
		//line a.y:380
		{
			outcode(int(yyDollar[1].lval), &nullgen, 0, &yyDollar[4].addr)
		}
	case 70:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:384
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 71:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:388
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 72:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:392
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[5].addr)
		}
	case 73:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:396
		{
			outcode(int(yyDollar[1].lval), &nullgen, int(yyDollar[2].lval), &yyDollar[4].addr)
		}
	case 74:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:400
		{
			outcode(int(yyDollar[1].lval), &nullgen, int(yyDollar[2].lval), &yyDollar[4].addr)
		}
	case 75:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:404
		{
			outcode(int(yyDollar[1].lval), &nullgen, int(yyDollar[2].lval), &yyDollar[5].addr)
		}
	case 76:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:408
		{
			var g obj.Addr
			g = nullgen
			g.Type = obj.TYPE_CONST
			g.Offset = yyDollar[2].lval
			outcode(int(yyDollar[1].lval), &g, int(REG_R0+yyDollar[4].lval), &yyDollar[6].addr)
		}
	case 77:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:416
		{
			var g obj.Addr
			g = nullgen
			g.Type = obj.TYPE_CONST
			g.Offset = yyDollar[2].lval
			outcode(int(yyDollar[1].lval), &g, int(REG_R0+yyDollar[4].lval), &yyDollar[6].addr)
		}
	case 78:
		yyDollar = yyS[yypt-8 : yypt+1]
		//line a.y:424
		{
			var g obj.Addr
			g = nullgen
			g.Type = obj.TYPE_CONST
			g.Offset = yyDollar[2].lval
			outcode(int(yyDollar[1].lval), &g, int(REG_R0+yyDollar[4].lval), &yyDollar[7].addr)
		}
	case 79:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:435
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].lval), &nullgen)
		}
	case 80:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:439
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].lval), &nullgen)
		}
	case 81:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:443
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &nullgen)
		}
	case 82:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:447
		{
			outcode(int(yyDollar[1].lval), &nullgen, 0, &nullgen)
		}
	case 83:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:454
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 84:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:458
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 85:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:462
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].addr.Reg), &yyDollar[6].addr)
		}
	case 86:
		yyDollar = yyS[yypt-8 : yypt+1]
		//line a.y:466
		{
			outgcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].addr.Reg), &yyDollar[6].addr, &yyDollar[8].addr)
		}
	case 87:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:470
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 88:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:474
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[6].addr.Reg), &yyDollar[4].addr)
		}
	case 89:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:481
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 90:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:485
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 91:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:489
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[6].addr.Reg), &yyDollar[4].addr)
		}
	case 92:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:493
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[6].addr.Reg), &yyDollar[4].addr)
		}
	case 93:
		yyDollar = yyS[yypt-8 : yypt+1]
		//line a.y:500
		{
			outgcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].addr.Reg), &yyDollar[6].addr, &yyDollar[8].addr)
		}
	case 94:
		yyDollar = yyS[yypt-8 : yypt+1]
		//line a.y:504
		{
			outgcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].addr.Reg), &yyDollar[6].addr, &yyDollar[8].addr)
		}
	case 95:
		yyDollar = yyS[yypt-8 : yypt+1]
		//line a.y:508
		{
			outgcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].addr.Reg), &yyDollar[6].addr, &yyDollar[8].addr)
		}
	case 96:
		yyDollar = yyS[yypt-8 : yypt+1]
		//line a.y:512
		{
			outgcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].addr.Reg), &yyDollar[6].addr, &yyDollar[8].addr)
		}
	case 97:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:519
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 98:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:523
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 99:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:531
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 100:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:535
		{
			outgcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr, &yyDollar[6].addr)
		}
	case 101:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:539
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 102:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:543
		{
			outgcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr, &yyDollar[6].addr)
		}
	case 103:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:547
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 104:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:551
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 105:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:555
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &nullgen)
		}
	case 106:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:562
		{
			outcode(int(yyDollar[1].lval), &nullgen, 0, &nullgen)
		}
	case 107:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:566
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &nullgen)
		}
	case 108:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:570
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &nullgen)
		}
	case 109:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:574
		{
			outcode(int(yyDollar[1].lval), &nullgen, 0, &yyDollar[3].addr)
		}
	case 110:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:578
		{
			outcode(int(yyDollar[1].lval), &nullgen, 0, &yyDollar[3].addr)
		}
	case 111:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:582
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &nullgen)
		}
	case 112:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:589
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &nullgen)
		}
	case 113:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:593
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &nullgen)
		}
	case 114:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:600
		{
			if yyDollar[2].addr.Type != obj.TYPE_CONST || yyDollar[4].addr.Type != obj.TYPE_CONST {
				yyerror("arguments to PCDATA must be integer constants")
			}
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 115:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:610
		{
			if yyDollar[2].addr.Type != obj.TYPE_CONST {
				yyerror("index for FUNCDATA must be integer constant")
			}
			if yyDollar[4].addr.Type != obj.TYPE_MEM || (yyDollar[4].addr.Name != obj.NAME_EXTERN && yyDollar[4].addr.Name != obj.NAME_STATIC) {
				yyerror("value for FUNCDATA must be symbol reference")
			}
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 116:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:623
		{
			outcode(int(yyDollar[1].lval), &nullgen, 0, &nullgen)
		}
	case 117:
		yyDollar = yyS[yypt-5 : yypt+1]
		//line a.y:630
		{
			asm.Settext(yyDollar[2].addr.Sym)
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[5].addr)
		}
	case 118:
		yyDollar = yyS[yypt-7 : yypt+1]
		//line a.y:635
		{
			asm.Settext(yyDollar[2].addr.Sym)
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, int(yyDollar[4].lval), &yyDollar[7].addr)
			if asm.Pass > 1 {
				lastpc.From3.Type = obj.TYPE_CONST
				lastpc.From3.Offset = yyDollar[4].lval
			}
		}
	case 119:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:647
		{
			asm.Settext(yyDollar[2].addr.Sym)
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 120:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:652
		{
			asm.Settext(yyDollar[2].addr.Sym)
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[6].addr)
			if asm.Pass > 1 {
				lastpc.From3.Type = obj.TYPE_CONST
				lastpc.From3.Offset = yyDollar[4].lval
			}
		}
	case 121:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:665
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[6].addr)
			if asm.Pass > 1 {
				lastpc.From3.Type = obj.TYPE_CONST
				lastpc.From3.Offset = yyDollar[4].lval
			}
		}
	case 122:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:673
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[6].addr)
			if asm.Pass > 1 {
				lastpc.From3.Type = obj.TYPE_CONST
				lastpc.From3.Offset = yyDollar[4].lval
			}
		}
	case 123:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:681
		{
			outcode(int(yyDollar[1].lval), &yyDollar[2].addr, 0, &yyDollar[6].addr)
			if asm.Pass > 1 {
				lastpc.From3.Type = obj.TYPE_CONST
				lastpc.From3.Offset = yyDollar[4].lval
			}
		}
	case 124:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:692
		{
			outcode(int(yyDollar[1].lval), &nullgen, 0, &nullgen)
		}
	case 125:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:698
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_BRANCH
			yyVAL.addr.Offset = yyDollar[1].lval + int64(asm.PC)
		}
	case 126:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:704
		{
			yyDollar[1].sym = asm.LabelLookup(yyDollar[1].sym)
			yyVAL.addr = nullgen
			if asm.Pass == 2 && yyDollar[1].sym.Type != LLAB {
				yyerror("undefined label: %s", yyDollar[1].sym.Labelname)
			}
			yyVAL.addr.Type = obj.TYPE_BRANCH
			yyVAL.addr.Offset = yyDollar[1].sym.Value + yyDollar[2].lval
		}
	case 127:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:716
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 128:
		yyVAL.addr = yyS[yypt-0].addr
	case 129:
		yyVAL.addr = yyS[yypt-0].addr
	case 130:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:728
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 131:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:736
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval) /* whole register */
		}
	case 132:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:743
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 133:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:751
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 134:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:759
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 135:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:765
		{
			if yyDollar[3].lval < 0 || yyDollar[3].lval >= 1024 {
				yyerror("SPR/DCR out of range")
			}
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval + yyDollar[3].lval)
		}
	case 136:
		yyVAL.addr = yyS[yypt-0].addr
	case 137:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:777
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 138:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:785
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 139:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:791
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(REG_F0 + yyDollar[3].lval)
		}
	case 140:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:799
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 141:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:805
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(REG_CR0 + yyDollar[3].lval)
		}
	case 142:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:813
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 143:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:821
		{
			var mb, me int
			var v uint32

			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_CONST
			mb = int(yyDollar[1].lval)
			me = int(yyDollar[3].lval)
			if mb < 0 || mb > 31 || me < 0 || me > 31 {
				yyerror("illegal mask start/end value(s)")
				mb = 0
				me = 0
			}
			if mb <= me {
				v = (^uint32(0) >> uint(mb)) & (^uint32(0) << uint(31-me))
			} else {
				v = (^uint32(0) >> uint(me+1)) & (^uint32(0) << uint(31-(mb-1)))
			}
			yyVAL.addr.Offset = int64(v)
		}
	case 144:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:844
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_TEXTSIZE
			yyVAL.addr.Offset = int64(yyDollar[1].lval)
			yyVAL.addr.Val = int32(obj.ArgsSizeUnknown)
		}
	case 145:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:851
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_TEXTSIZE
			yyVAL.addr.Offset = -int64(yyDollar[2].lval)
			yyVAL.addr.Val = int32(obj.ArgsSizeUnknown)
		}
	case 146:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:858
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_TEXTSIZE
			yyVAL.addr.Offset = int64(yyDollar[1].lval)
			yyVAL.addr.Val = int32(yyDollar[3].lval)
		}
	case 147:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:865
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_TEXTSIZE
			yyVAL.addr.Offset = -int64(yyDollar[2].lval)
			yyVAL.addr.Val = int32(yyDollar[4].lval)
		}
	case 148:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:874
		{
			yyVAL.addr = yyDollar[2].addr
			yyVAL.addr.Type = obj.TYPE_ADDR
		}
	case 149:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:879
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_SCONST
			yyVAL.addr.Val = yyDollar[2].sval
		}
	case 150:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:887
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_FCONST
			yyVAL.addr.Val = yyDollar[2].dval
		}
	case 151:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:893
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_FCONST
			yyVAL.addr.Val = -yyDollar[3].dval
		}
	case 152:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:900
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_CONST
			yyVAL.addr.Offset = yyDollar[2].lval
		}
	case 153:
		yyVAL.lval = yyS[yypt-0].lval
	case 154:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:909
		{
			if yyVAL.lval < 0 || yyVAL.lval >= NREG {
				print("register value out of range\n")
			}
			yyVAL.lval = REG_R0 + yyDollar[3].lval
		}
	case 155:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:918
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Reg = int16(yyDollar[2].lval)
			yyVAL.addr.Offset = 0
		}
	case 156:
		yyDollar = yyS[yypt-5 : yypt+1]
		//line a.y:925
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Reg = int16(yyDollar[2].lval)
			yyVAL.addr.Scale = int16(yyDollar[4].lval)
			yyVAL.addr.Offset = 0
		}
	case 157:
		yyVAL.addr = yyS[yypt-0].addr
	case 158:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:936
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Reg = int16(yyDollar[3].lval)
			yyVAL.addr.Offset = yyDollar[1].lval
		}
	case 159:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:945
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Name = int8(yyDollar[3].lval)
			yyVAL.addr.Sym = nil
			yyVAL.addr.Offset = yyDollar[1].lval
		}
	case 160:
		yyDollar = yyS[yypt-5 : yypt+1]
		//line a.y:953
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Name = int8(yyDollar[4].lval)
			yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyDollar[1].sym.Name, 0)
			yyVAL.addr.Offset = yyDollar[2].lval
		}
	case 161:
		yyDollar = yyS[yypt-7 : yypt+1]
		//line a.y:961
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Name = obj.NAME_STATIC
			yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyDollar[1].sym.Name, 1)
			yyVAL.addr.Offset = yyDollar[4].lval
		}
	case 164:
		yyDollar = yyS[yypt-0 : yypt+1]
		//line a.y:973
		{
			yyVAL.lval = 0
		}
	case 165:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:977
		{
			yyVAL.lval = yyDollar[2].lval
		}
	case 166:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:981
		{
			yyVAL.lval = -yyDollar[2].lval
		}
	case 167:
		yyVAL.lval = yyS[yypt-0].lval
	case 168:
		yyVAL.lval = yyS[yypt-0].lval
	case 169:
		yyVAL.lval = yyS[yypt-0].lval
	case 170:
		yyVAL.lval = yyS[yypt-0].lval
	case 171:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:993
		{
			yyVAL.lval = yyDollar[1].sym.Value
		}
	case 172:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:997
		{
			yyVAL.lval = -yyDollar[2].lval
		}
	case 173:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:1001
		{
			yyVAL.lval = yyDollar[2].lval
		}
	case 174:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:1005
		{
			yyVAL.lval = ^yyDollar[2].lval
		}
	case 175:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:1009
		{
			yyVAL.lval = yyDollar[2].lval
		}
	case 176:
		yyVAL.lval = yyS[yypt-0].lval
	case 177:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:1016
		{
			yyVAL.lval = yyDollar[1].lval + yyDollar[3].lval
		}
	case 178:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:1020
		{
			yyVAL.lval = yyDollar[1].lval - yyDollar[3].lval
		}
	case 179:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:1024
		{
			yyVAL.lval = yyDollar[1].lval * yyDollar[3].lval
		}
	case 180:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:1028
		{
			yyVAL.lval = yyDollar[1].lval / yyDollar[3].lval
		}
	case 181:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:1032
		{
			yyVAL.lval = yyDollar[1].lval % yyDollar[3].lval
		}
	case 182:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:1036
		{
			yyVAL.lval = yyDollar[1].lval << uint(yyDollar[4].lval)
		}
	case 183:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:1040
		{
			yyVAL.lval = yyDollar[1].lval >> uint(yyDollar[4].lval)
		}
	case 184:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:1044
		{
			yyVAL.lval = yyDollar[1].lval & yyDollar[3].lval
		}
	case 185:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:1048
		{
			yyVAL.lval = yyDollar[1].lval ^ yyDollar[3].lval
		}
	case 186:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:1052
		{
			yyVAL.lval = yyDollar[1].lval | yyDollar[3].lval
		}
	}
	goto yystack /* stack new state and value */
}
コード例 #19
0
ファイル: peep.go プロジェクト: xiezerozero/go
/*
 * xtramodes enables the ARM post increment and
 * shift offset addressing modes to transform
 *   MOVW   0(R3),R1
 *   ADD    $4,R3,R3
 * into
 *   MOVW.P 4(R3),R1
 * and
 *   ADD    R0,R1
 *   MOVBU  0(R1),R0
 * into
 *   MOVBU  R0<<0(R1),R0
 */
func xtramodes(g *gc.Graph, r *gc.Flow, a *obj.Addr) bool {
	p := (*obj.Prog)(r.Prog)
	v := obj.Addr(*a)
	v.Type = obj.TYPE_REG
	r1 := (*gc.Flow)(findpre(r, &v))
	if r1 != nil {
		p1 := r1.Prog
		if p1.To.Type == obj.TYPE_REG && p1.To.Reg == v.Reg {
			switch p1.As {
			case arm.AADD:
				if p1.Scond&arm.C_SBIT != 0 {
					// avoid altering ADD.S/ADC sequences.
					break
				}

				if p1.From.Type == obj.TYPE_REG || (p1.From.Type == obj.TYPE_SHIFT && p1.From.Offset&(1<<4) == 0 && ((p.As != arm.AMOVB && p.As != arm.AMOVBS) || (a == &p.From && p1.From.Offset&^0xf == 0))) || ((p1.From.Type == obj.TYPE_ADDR || p1.From.Type == obj.TYPE_CONST) && p1.From.Offset > -4096 && p1.From.Offset < 4096) {
					if nochange(gc.Uniqs(r1), r, p1) {
						if a != &p.From || v.Reg != p.To.Reg {
							if finduse(g, r.S1, &v) {
								if p1.Reg == 0 || p1.Reg == v.Reg {
									/* pre-indexing */
									p.Scond |= arm.C_WBIT
								} else {
									return false
								}
							}
						}

						switch p1.From.Type {
						/* register offset */
						case obj.TYPE_REG:
							if gc.Nacl {
								return false
							}
							*a = obj.Addr{}
							a.Type = obj.TYPE_SHIFT
							a.Offset = int64(p1.From.Reg) & 15

							/* scaled register offset */
						case obj.TYPE_SHIFT:
							if gc.Nacl {
								return false
							}
							*a = obj.Addr{}
							a.Type = obj.TYPE_SHIFT
							fallthrough

							/* immediate offset */
						case obj.TYPE_CONST,
							obj.TYPE_ADDR:
							a.Offset = p1.From.Offset
						}

						if p1.Reg != 0 {
							a.Reg = p1.Reg
						}
						excise(r1)
						return true
					}
				}

			case arm.AMOVW:
				if p1.From.Type == obj.TYPE_REG {
					r2 := (*gc.Flow)(findinc(r1, r, &p1.From))
					if r2 != nil {
						var r3 *gc.Flow
						for r3 = gc.Uniqs(r2); r3.Prog.As == obj.ANOP; r3 = gc.Uniqs(r3) {
						}
						if r3 == r {
							/* post-indexing */
							p1 := r2.Prog

							a.Reg = p1.To.Reg
							a.Offset = p1.From.Offset
							p.Scond |= arm.C_PBIT
							if !finduse(g, r, &r1.Prog.To) {
								excise(r1)
							}
							excise(r2)
							return true
						}
					}
				}
			}
		}
	}

	if a != &p.From || a.Reg != p.To.Reg {
		r1 := (*gc.Flow)(findinc(r, nil, &v))
		if r1 != nil {
			/* post-indexing */
			p1 := r1.Prog

			a.Offset = p1.From.Offset
			p.Scond |= arm.C_PBIT
			excise(r1)
			return true
		}
	}

	return false
}
コード例 #20
0
ファイル: gsubr.go プロジェクト: hurkgu/go
// Naddr rewrites a to refer to n.
// It assumes that a is zeroed on entry.
func Naddr(a *obj.Addr, n *Node) {
	if n == nil {
		return
	}

	if n.Type != nil && n.Type.Etype != TIDEAL {
		// TODO(rsc): This is undone by the selective clearing of width below,
		// to match architectures that were not as aggressive in setting width
		// during naddr. Those widths must be cleared to avoid triggering
		// failures in gins when it detects real but heretofore latent (and one
		// hopes innocuous) type mismatches.
		// The type mismatches should be fixed and the clearing below removed.
		dowidth(n.Type)

		a.Width = n.Type.Width
	}

	switch n.Op {
	default:
		a := a // copy to let escape into Ctxt.Dconv
		Debug['h'] = 1
		Dump("naddr", n)
		Fatalf("naddr: bad %v %v", n.Op, Ctxt.Dconv(a))

	case OREGISTER:
		a.Type = obj.TYPE_REG
		a.Reg = n.Reg
		a.Sym = nil
		if Thearch.LinkArch.Family == sys.I386 { // TODO(rsc): Never clear a->width.
			a.Width = 0
		}

	case OINDREG:
		a.Type = obj.TYPE_MEM
		a.Reg = n.Reg
		a.Sym = Linksym(n.Sym)
		a.Offset = n.Xoffset
		if a.Offset != int64(int32(a.Offset)) {
			Yyerror("offset %d too large for OINDREG", a.Offset)
		}
		if Thearch.LinkArch.Family == sys.I386 { // TODO(rsc): Never clear a->width.
			a.Width = 0
		}

	case OCLOSUREVAR:
		if !Curfn.Func.Needctxt {
			Fatalf("closurevar without needctxt")
		}
		a.Type = obj.TYPE_MEM
		a.Reg = int16(Thearch.REGCTXT)
		a.Sym = nil
		a.Offset = n.Xoffset

	case OCFUNC:
		Naddr(a, n.Left)
		a.Sym = Linksym(n.Left.Sym)

	case ONAME:
		a.Etype = 0
		if n.Type != nil {
			a.Etype = uint8(Simtype[n.Type.Etype])
		}
		a.Offset = n.Xoffset
		s := n.Sym
		a.Node = n.Orig

		//if(a->node >= (Node*)&n)
		//	fatal("stack node");
		if s == nil {
			s = Lookup(".noname")
		}
		if n.Name.Method && n.Type != nil && n.Type.Sym != nil && n.Type.Sym.Pkg != nil {
			s = Pkglookup(s.Name, n.Type.Sym.Pkg)
		}

		a.Type = obj.TYPE_MEM
		switch n.Class {
		default:
			Fatalf("naddr: ONAME class %v %d\n", n.Sym, n.Class)

		case PEXTERN:
			a.Name = obj.NAME_EXTERN

		case PAUTO:
			a.Name = obj.NAME_AUTO

		case PPARAM, PPARAMOUT:
			a.Name = obj.NAME_PARAM

		case PFUNC:
			a.Name = obj.NAME_EXTERN
			a.Type = obj.TYPE_ADDR
			a.Width = int64(Widthptr)
			s = funcsym(s)
		}

		a.Sym = Linksym(s)

	case ODOT:
		// A special case to make write barriers more efficient.
		// Taking the address of the first field of a named struct
		// is the same as taking the address of the struct.
		if !n.Left.Type.IsStruct() || n.Left.Type.Field(0).Sym != n.Sym {
			Debug['h'] = 1
			Dump("naddr", n)
			Fatalf("naddr: bad %v %v", n.Op, Ctxt.Dconv(a))
		}
		Naddr(a, n.Left)

	case OLITERAL:
		if Thearch.LinkArch.Family == sys.I386 {
			a.Width = 0
		}
		switch u := n.Val().U.(type) {
		default:
			Fatalf("naddr: const %v", Tconv(n.Type, FmtLong))

		case *Mpflt:
			a.Type = obj.TYPE_FCONST
			a.Val = u.Float64()

		case *Mpint:
			a.Sym = nil
			a.Type = obj.TYPE_CONST
			a.Offset = u.Int64()

		case string:
			datagostring(u, a)

		case bool:
			a.Sym = nil
			a.Type = obj.TYPE_CONST
			a.Offset = int64(obj.Bool2int(u))

		case *NilVal:
			a.Sym = nil
			a.Type = obj.TYPE_CONST
			a.Offset = 0
		}

	case OADDR:
		Naddr(a, n.Left)
		a.Etype = uint8(Tptr)
		if !Thearch.LinkArch.InFamily(sys.MIPS64, sys.ARM, sys.ARM64, sys.PPC64, sys.S390X) { // TODO(rsc): Do this even for these architectures.
			a.Width = int64(Widthptr)
		}
		if a.Type != obj.TYPE_MEM {
			a := a // copy to let escape into Ctxt.Dconv
			Fatalf("naddr: OADDR %v (from %v)", Ctxt.Dconv(a), n.Left.Op)
		}
		a.Type = obj.TYPE_ADDR

	case OITAB:
		// itable of interface value
		Naddr(a, n.Left)
		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
			break // itab(nil)
		}
		a.Etype = uint8(Tptr)
		a.Width = int64(Widthptr)

	case OIDATA:
		// idata of interface value
		Naddr(a, n.Left)
		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
			break // idata(nil)
		}
		if isdirectiface(n.Type) {
			a.Etype = uint8(Simtype[n.Type.Etype])
		} else {
			a.Etype = uint8(Tptr)
		}
		a.Offset += int64(Widthptr)
		a.Width = int64(Widthptr)

		// pointer in a string or slice
	case OSPTR:
		Naddr(a, n.Left)

		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
			break // ptr(nil)
		}
		a.Etype = uint8(Simtype[Tptr])
		a.Offset += int64(Array_array)
		a.Width = int64(Widthptr)

		// len of string or slice
	case OLEN:
		Naddr(a, n.Left)

		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
			break // len(nil)
		}
		a.Etype = uint8(Simtype[TUINT])
		a.Offset += int64(Array_nel)
		if Thearch.LinkArch.Family != sys.ARM { // TODO(rsc): Do this even on arm.
			a.Width = int64(Widthint)
		}

		// cap of string or slice
	case OCAP:
		Naddr(a, n.Left)

		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
			break // cap(nil)
		}
		a.Etype = uint8(Simtype[TUINT])
		a.Offset += int64(Array_cap)
		if Thearch.LinkArch.Family != sys.ARM { // TODO(rsc): Do this even on arm.
			a.Width = int64(Widthint)
		}
	}
}
コード例 #21
0
ファイル: gsubr.go プロジェクト: Greentor/go
/*
 * generate code to compute address of n,
 * a reference to a (perhaps nested) field inside
 * an array or struct.
 * return 0 on failure, 1 on success.
 * on success, leaves usable address in a.
 *
 * caller is responsible for calling sudoclean
 * after successful sudoaddable,
 * to release the register used for a.
 */
func sudoaddable(as obj.As, n *gc.Node, a *obj.Addr) bool {
	if n.Type == nil {
		return false
	}

	*a = obj.Addr{}

	switch n.Op {
	case gc.OLITERAL:
		if !gc.Isconst(n, gc.CTINT) {
			return false
		}
		v := n.Int64()
		switch as {
		default:
			return false

		// operations that can cope with a 32-bit immediate
		// TODO(mundaym): logical operations can work on high bits
		case s390x.AADD,
			s390x.AADDC,
			s390x.ASUB,
			s390x.AMULLW,
			s390x.AAND,
			s390x.AOR,
			s390x.AXOR,
			s390x.ASLD,
			s390x.ASLW,
			s390x.ASRAW,
			s390x.ASRAD,
			s390x.ASRW,
			s390x.ASRD,
			s390x.AMOVB,
			s390x.AMOVBZ,
			s390x.AMOVH,
			s390x.AMOVHZ,
			s390x.AMOVW,
			s390x.AMOVWZ,
			s390x.AMOVD:
			if int64(int32(v)) != v {
				return false
			}

		// for comparisons avoid immediates unless they can
		// fit into a int8/uint8
		// this favours combined compare and branch instructions
		case s390x.ACMP:
			if int64(int8(v)) != v {
				return false
			}
		case s390x.ACMPU:
			if int64(uint8(v)) != v {
				return false
			}
		}

		cleani += 2
		reg := &clean[cleani-1]
		reg1 := &clean[cleani-2]
		reg.Op = gc.OEMPTY
		reg1.Op = gc.OEMPTY
		gc.Naddr(a, n)
		return true

	case gc.ODOT,
		gc.ODOTPTR:
		cleani += 2
		reg := &clean[cleani-1]
		reg1 := &clean[cleani-2]
		reg.Op = gc.OEMPTY
		reg1.Op = gc.OEMPTY
		var nn *gc.Node
		var oary [10]int64
		o := gc.Dotoffset(n, oary[:], &nn)
		if nn == nil {
			sudoclean()
			return false
		}

		if nn.Addable && o == 1 && oary[0] >= 0 {
			// directly addressable set of DOTs
			n1 := *nn

			n1.Type = n.Type
			n1.Xoffset += oary[0]
			// check that the offset fits into a 12-bit displacement
			if n1.Xoffset < 0 || n1.Xoffset >= (1<<12)-8 {
				sudoclean()
				return false
			}
			gc.Naddr(a, &n1)
			return true
		}

		gc.Regalloc(reg, gc.Types[gc.Tptr], nil)
		n1 := *reg
		n1.Op = gc.OINDREG
		if oary[0] >= 0 {
			gc.Agen(nn, reg)
			n1.Xoffset = oary[0]
		} else {
			gc.Cgen(nn, reg)
			gc.Cgen_checknil(reg)
			n1.Xoffset = -(oary[0] + 1)
		}

		for i := 1; i < o; i++ {
			if oary[i] >= 0 {
				gc.Fatalf("can't happen")
			}
			gins(s390x.AMOVD, &n1, reg)
			gc.Cgen_checknil(reg)
			n1.Xoffset = -(oary[i] + 1)
		}

		a.Type = obj.TYPE_NONE
		a.Index = 0
		// check that the offset fits into a 12-bit displacement
		if n1.Xoffset < 0 || n1.Xoffset >= (1<<12)-8 {
			tmp := n1
			tmp.Op = gc.OREGISTER
			tmp.Type = gc.Types[gc.Tptr]
			tmp.Xoffset = 0
			gc.Cgen_checknil(&tmp)
			ginscon(s390x.AADD, n1.Xoffset, &tmp)
			n1.Xoffset = 0
		}
		gc.Naddr(a, &n1)
		return true
	}

	return false
}
コード例 #22
0
ファイル: gsubr.go プロジェクト: Ryezhang/go
func Afunclit(a *obj.Addr, n *Node) {
	if a.Type == obj.TYPE_ADDR && a.Name == obj.NAME_EXTERN {
		a.Type = obj.TYPE_MEM
		a.Sym = Linksym(n.Sym)
	}
}
コード例 #23
0
ファイル: gsubr.go プロジェクト: kuangchanglang/go
func Addrconst(a *obj.Addr, v int64) {
	a.Sym = nil
	a.Type = obj.TYPE_CONST
	a.Offset = v
}
コード例 #24
0
// operand parses a general operand and stores the result in *a.
func (p *Parser) operand(a *obj.Addr) bool {
	//fmt.Printf("Operand: %v\n", p.input)
	if len(p.input) == 0 {
		p.errorf("empty operand: cannot happen")
		return false
	}
	// 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) {
		// 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 true
		}
	}

	// 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.expect(scanner.EOF)
		return true
	}

	// 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 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.expect(scanner.EOF)
		return true
	}

	// Constant.
	haveConstant := false
	switch tok.ScanToken {
	case scanner.Int, scanner.Float, scanner.String, scanner.Char, '+', '-', '~':
		haveConstant = true
	case '(':
		// Could be parenthesized expression or (R).
		rname := p.next().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.expect(scanner.EOF)
			return true
		}
		if p.have(scanner.String) {
			if prefix != '$' {
				p.errorf("string constant must be an immediate")
			}
			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.expect(scanner.EOF)
			return true
		}
		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.expect(scanner.EOF)
			return true
		}
		// 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.expect(scanner.EOF)
	return true
}
コード例 #25
0
ファイル: gsubr.go プロジェクト: wheelcomplex/go-1
/*
 * generate code to compute address of n,
 * a reference to a (perhaps nested) field inside
 * an array or struct.
 * return 0 on failure, 1 on success.
 * on success, leaves usable address in a.
 *
 * caller is responsible for calling sudoclean
 * after successful sudoaddable,
 * to release the register used for a.
 */
func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool {
	if n.Type == nil {
		return false
	}

	*a = obj.Addr{}

	switch n.Op {
	case gc.OLITERAL:
		if !gc.Isconst(n, gc.CTINT) {
			break
		}
		v := n.Int()
		if v >= 32000 || v <= -32000 {
			break
		}
		switch as {
		default:
			return false

		case arm.AADD,
			arm.ASUB,
			arm.AAND,
			arm.AORR,
			arm.AEOR,
			arm.AMOVB,
			arm.AMOVBS,
			arm.AMOVBU,
			arm.AMOVH,
			arm.AMOVHS,
			arm.AMOVHU,
			arm.AMOVW:
			break
		}

		cleani += 2
		reg := &clean[cleani-1]
		reg1 := &clean[cleani-2]
		reg.Op = gc.OEMPTY
		reg1.Op = gc.OEMPTY
		gc.Naddr(a, n)
		return true

	case gc.ODOT,
		gc.ODOTPTR:
		cleani += 2
		reg := &clean[cleani-1]
		reg1 := &clean[cleani-2]
		reg.Op = gc.OEMPTY
		reg1.Op = gc.OEMPTY
		var nn *gc.Node
		var oary [10]int64
		o := gc.Dotoffset(n, oary[:], &nn)
		if nn == nil {
			sudoclean()
			return false
		}

		if nn.Addable && o == 1 && oary[0] >= 0 {
			// directly addressable set of DOTs
			n1 := *nn

			n1.Type = n.Type
			n1.Xoffset += oary[0]
			gc.Naddr(a, &n1)
			return true
		}

		gc.Regalloc(reg, gc.Types[gc.Tptr], nil)
		n1 := *reg
		n1.Op = gc.OINDREG
		if oary[0] >= 0 {
			gc.Agen(nn, reg)
			n1.Xoffset = oary[0]
		} else {
			gc.Cgen(nn, reg)
			gc.Cgen_checknil(reg)
			n1.Xoffset = -(oary[0] + 1)
		}

		for i := 1; i < o; i++ {
			if oary[i] >= 0 {
				gc.Fatal("can't happen")
			}
			gins(arm.AMOVW, &n1, reg)
			gc.Cgen_checknil(reg)
			n1.Xoffset = -(oary[i] + 1)
		}

		a.Type = obj.TYPE_NONE
		a.Name = obj.NAME_NONE
		n1.Type = n.Type
		gc.Naddr(a, &n1)
		return true

	case gc.OINDEX:
		return false
	}

	return false
}
コード例 #26
0
ファイル: peep.go プロジェクト: hurkgu/go
/*
 * ASLL x,y,w
 * .. (not use w, not set x y w)
 * AXXX w,a,b (a != w)
 * .. (not use w)
 * (set w)
 * ----------- changed to
 * ..
 * AXXX (x<<y),a,b
 * ..
 */
func shiftprop(r *gc.Flow) bool {
	p := r.Prog
	if p.To.Type != obj.TYPE_REG {
		if gc.Debug['P'] != 0 {
			fmt.Printf("\tBOTCH: result not reg; FAILURE\n")
		}
		return false
	}

	n := p.To.Reg
	var a obj.Addr
	if p.Reg != 0 && p.Reg != p.To.Reg {
		a.Type = obj.TYPE_REG
		a.Reg = p.Reg
	}

	if gc.Debug['P'] != 0 {
		fmt.Printf("shiftprop\n%v", p)
	}
	r1 := r
	var p1 *obj.Prog
	for {
		/* find first use of shift result; abort if shift operands or result are changed */
		r1 = gc.Uniqs(r1)

		if r1 == nil {
			if gc.Debug['P'] != 0 {
				fmt.Printf("\tbranch; FAILURE\n")
			}
			return false
		}

		if gc.Uniqp(r1) == nil {
			if gc.Debug['P'] != 0 {
				fmt.Printf("\tmerge; FAILURE\n")
			}
			return false
		}

		p1 = r1.Prog
		if gc.Debug['P'] != 0 {
			fmt.Printf("\n%v", p1)
		}
		switch copyu(p1, &p.To, nil) {
		case 0: /* not used or set */
			if (p.From.Type == obj.TYPE_REG && copyu(p1, &p.From, nil) > 1) || (a.Type == obj.TYPE_REG && copyu(p1, &a, nil) > 1) {
				if gc.Debug['P'] != 0 {
					fmt.Printf("\targs modified; FAILURE\n")
				}
				return false
			}

			continue
		case 3: /* set, not used */
			{
				if gc.Debug['P'] != 0 {
					fmt.Printf("\tBOTCH: noref; FAILURE\n")
				}
				return false
			}
		}

		break
	}

	/* check whether substitution can be done */
	switch p1.As {
	default:
		if gc.Debug['P'] != 0 {
			fmt.Printf("\tnon-dpi; FAILURE\n")
		}
		return false

	case arm.AAND,
		arm.AEOR,
		arm.AADD,
		arm.AADC,
		arm.AORR,
		arm.ASUB,
		arm.ASBC,
		arm.ARSB,
		arm.ARSC:
		if p1.Reg == n || (p1.Reg == 0 && p1.To.Type == obj.TYPE_REG && p1.To.Reg == n) {
			if p1.From.Type != obj.TYPE_REG {
				if gc.Debug['P'] != 0 {
					fmt.Printf("\tcan't swap; FAILURE\n")
				}
				return false
			}

			p1.Reg = p1.From.Reg
			p1.From.Reg = n
			switch p1.As {
			case arm.ASUB:
				p1.As = arm.ARSB

			case arm.ARSB:
				p1.As = arm.ASUB

			case arm.ASBC:
				p1.As = arm.ARSC

			case arm.ARSC:
				p1.As = arm.ASBC
			}

			if gc.Debug['P'] != 0 {
				fmt.Printf("\t=>%v", p1)
			}
		}
		fallthrough

	case arm.ABIC,
		arm.ATST,
		arm.ACMP,
		arm.ACMN:
		if p1.Reg == n {
			if gc.Debug['P'] != 0 {
				fmt.Printf("\tcan't swap; FAILURE\n")
			}
			return false
		}

		if p1.Reg == 0 && p1.To.Reg == n {
			if gc.Debug['P'] != 0 {
				fmt.Printf("\tshift result used twice; FAILURE\n")
			}
			return false
		}

		//	case AMVN:
		if p1.From.Type == obj.TYPE_SHIFT {
			if gc.Debug['P'] != 0 {
				fmt.Printf("\tshift result used in shift; FAILURE\n")
			}
			return false
		}

		if p1.From.Type != obj.TYPE_REG || p1.From.Reg != n {
			if gc.Debug['P'] != 0 {
				fmt.Printf("\tBOTCH: where is it used?; FAILURE\n")
			}
			return false
		}
	}

	/* check whether shift result is used subsequently */
	p2 := p1

	if p1.To.Reg != n {
		var p1 *obj.Prog
		for {
			r1 = gc.Uniqs(r1)
			if r1 == nil {
				if gc.Debug['P'] != 0 {
					fmt.Printf("\tinconclusive; FAILURE\n")
				}
				return false
			}

			p1 = r1.Prog
			if gc.Debug['P'] != 0 {
				fmt.Printf("\n%v", p1)
			}
			switch copyu(p1, &p.To, nil) {
			case 0: /* not used or set */
				continue

			case 3: /* set, not used */
				break

			default: /* used */
				if gc.Debug['P'] != 0 {
					fmt.Printf("\treused; FAILURE\n")
				}
				return false
			}

			break
		}
	}

	/* make the substitution */
	p2.From.Reg = 0
	o := p.Reg
	if o == 0 {
		o = p.To.Reg
	}
	o &= 15

	switch p.From.Type {
	case obj.TYPE_CONST:
		o |= int16(p.From.Offset&0x1f) << 7

	case obj.TYPE_REG:
		o |= 1<<4 | (p.From.Reg&15)<<8
	}

	switch p.As {
	case arm.ASLL:
		o |= 0 << 5

	case arm.ASRL:
		o |= 1 << 5

	case arm.ASRA:
		o |= 2 << 5
	}

	p2.From = obj.Addr{}
	p2.From.Type = obj.TYPE_SHIFT
	p2.From.Offset = int64(o)
	if gc.Debug['P'] != 0 {
		fmt.Printf("\t=>%v\tSUCCEED\n", p2)
	}
	return true
}
コード例 #27
0
ファイル: gsubr.go プロジェクト: Ryezhang/go
// Naddr rewrites a to refer to n.
// It assumes that a is zeroed on entry.
func Naddr(a *obj.Addr, n *Node) {
	if n == nil {
		return
	}

	if n.Type != nil && n.Type.Etype != TIDEAL {
		// TODO(rsc): This is undone by the selective clearing of width below,
		// to match architectures that were not as aggressive in setting width
		// during naddr. Those widths must be cleared to avoid triggering
		// failures in gins when it detects real but heretofore latent (and one
		// hopes innocuous) type mismatches.
		// The type mismatches should be fixed and the clearing below removed.
		dowidth(n.Type)

		a.Width = n.Type.Width
	}

	switch n.Op {
	default:
		a := a // copy to let escape into Ctxt.Dconv
		Debug['h'] = 1
		Dump("naddr", n)
		Fatalf("naddr: bad %v %v", Oconv(int(n.Op), 0), Ctxt.Dconv(a))

	case OREGISTER:
		a.Type = obj.TYPE_REG
		a.Reg = n.Reg
		a.Sym = nil
		if Thearch.Thechar == '8' { // TODO(rsc): Never clear a->width.
			a.Width = 0
		}

	case OINDREG:
		a.Type = obj.TYPE_MEM
		a.Reg = n.Reg
		a.Sym = Linksym(n.Sym)
		a.Offset = n.Xoffset
		if a.Offset != int64(int32(a.Offset)) {
			Yyerror("offset %d too large for OINDREG", a.Offset)
		}
		if Thearch.Thechar == '8' { // TODO(rsc): Never clear a->width.
			a.Width = 0
		}

		// n->left is PHEAP ONAME for stack parameter.
	// compute address of actual parameter on stack.
	case OPARAM:
		a.Etype = uint8(Simtype[n.Left.Type.Etype])

		a.Width = n.Left.Type.Width
		a.Offset = n.Xoffset
		a.Sym = Linksym(n.Left.Sym)
		a.Type = obj.TYPE_MEM
		a.Name = obj.NAME_PARAM
		a.Node = n.Left.Orig

	case OCLOSUREVAR:
		if !Curfn.Func.Needctxt {
			Fatalf("closurevar without needctxt")
		}
		a.Type = obj.TYPE_MEM
		a.Reg = int16(Thearch.REGCTXT)
		a.Sym = nil
		a.Offset = n.Xoffset

	case OCFUNC:
		Naddr(a, n.Left)
		a.Sym = Linksym(n.Left.Sym)

	case ONAME:
		a.Etype = 0
		if n.Type != nil {
			a.Etype = uint8(Simtype[n.Type.Etype])
		}
		a.Offset = n.Xoffset
		s := n.Sym
		a.Node = n.Orig

		//if(a->node >= (Node*)&n)
		//	fatal("stack node");
		if s == nil {
			s = Lookup(".noname")
		}
		if n.Name.Method {
			if n.Type != nil {
				if n.Type.Sym != nil {
					if n.Type.Sym.Pkg != nil {
						s = Pkglookup(s.Name, n.Type.Sym.Pkg)
					}
				}
			}
		}

		a.Type = obj.TYPE_MEM
		switch n.Class {
		default:
			Fatalf("naddr: ONAME class %v %d\n", n.Sym, n.Class)

		case PEXTERN:
			a.Name = obj.NAME_EXTERN

		case PAUTO:
			a.Name = obj.NAME_AUTO

		case PPARAM, PPARAMOUT:
			a.Name = obj.NAME_PARAM

		case PFUNC:
			a.Name = obj.NAME_EXTERN
			a.Type = obj.TYPE_ADDR
			a.Width = int64(Widthptr)
			s = funcsym(s)
		}

		a.Sym = Linksym(s)

	case OLITERAL:
		if Thearch.Thechar == '8' {
			a.Width = 0
		}
		switch n.Val().Ctype() {
		default:
			Fatalf("naddr: const %v", Tconv(n.Type, obj.FmtLong))

		case CTFLT:
			a.Type = obj.TYPE_FCONST
			a.Val = mpgetflt(n.Val().U.(*Mpflt))

		case CTINT, CTRUNE:
			a.Sym = nil
			a.Type = obj.TYPE_CONST
			a.Offset = Mpgetfix(n.Val().U.(*Mpint))

		case CTSTR:
			datagostring(n.Val().U.(string), a)

		case CTBOOL:
			a.Sym = nil
			a.Type = obj.TYPE_CONST
			a.Offset = int64(obj.Bool2int(n.Val().U.(bool)))

		case CTNIL:
			a.Sym = nil
			a.Type = obj.TYPE_CONST
			a.Offset = 0
		}

	case OADDR:
		Naddr(a, n.Left)
		a.Etype = uint8(Tptr)
		if Thearch.Thechar != '0' && Thearch.Thechar != '5' && Thearch.Thechar != '7' && Thearch.Thechar != '9' { // TODO(rsc): Do this even for arm, ppc64.
			a.Width = int64(Widthptr)
		}
		if a.Type != obj.TYPE_MEM {
			a := a // copy to let escape into Ctxt.Dconv
			Fatalf("naddr: OADDR %v (from %v)", Ctxt.Dconv(a), Oconv(int(n.Left.Op), 0))
		}
		a.Type = obj.TYPE_ADDR

		// itable of interface value
	case OITAB:
		Naddr(a, n.Left)

		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
			break // itab(nil)
		}
		a.Etype = uint8(Tptr)
		a.Width = int64(Widthptr)

		// pointer in a string or slice
	case OSPTR:
		Naddr(a, n.Left)

		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
			break // ptr(nil)
		}
		a.Etype = uint8(Simtype[Tptr])
		a.Offset += int64(Array_array)
		a.Width = int64(Widthptr)

		// len of string or slice
	case OLEN:
		Naddr(a, n.Left)

		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
			break // len(nil)
		}
		a.Etype = uint8(Simtype[TUINT])
		a.Offset += int64(Array_nel)
		if Thearch.Thechar != '5' { // TODO(rsc): Do this even on arm.
			a.Width = int64(Widthint)
		}

		// cap of string or slice
	case OCAP:
		Naddr(a, n.Left)

		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
			break // cap(nil)
		}
		a.Etype = uint8(Simtype[TUINT])
		a.Offset += int64(Array_cap)
		if Thearch.Thechar != '5' { // TODO(rsc): Do this even on arm.
			a.Width = int64(Widthint)
		}
	}
	return
}
コード例 #28
0
ファイル: y.go プロジェクト: Ericean/go
func (yyrcvr *yyParserImpl) Parse(yylex yyLexer) int {
	var yyn int
	var yylval yySymType
	var yyVAL yySymType
	var yyDollar []yySymType
	yyS := make([]yySymType, yyMaxDepth)

	Nerrs := 0   /* number of errors */
	Errflag := 0 /* error recovery flag */
	yystate := 0
	yychar := -1
	yytoken := -1 // yychar translated into internal numbering
	yyrcvr.lookahead = func() int { return yychar }
	defer func() {
		// Make sure we report no lookahead when not parsing.
		yystate = -1
		yychar = -1
		yytoken = -1
	}()
	yyp := -1
	goto yystack

ret0:
	return 0

ret1:
	return 1

yystack:
	/* put a state and value onto the stack */
	if yyDebug >= 4 {
		__yyfmt__.Printf("char %v in %v\n", yyTokname(yytoken), yyStatname(yystate))
	}

	yyp++
	if yyp >= len(yyS) {
		nyys := make([]yySymType, len(yyS)*2)
		copy(nyys, yyS)
		yyS = nyys
	}
	yyS[yyp] = yyVAL
	yyS[yyp].yys = yystate

yynewstate:
	yyn = yyPact[yystate]
	if yyn <= yyFlag {
		goto yydefault /* simple state */
	}
	if yychar < 0 {
		yychar, yytoken = yylex1(yylex, &yylval)
	}
	yyn += yytoken
	if yyn < 0 || yyn >= yyLast {
		goto yydefault
	}
	yyn = yyAct[yyn]
	if yyChk[yyn] == yytoken { /* valid shift */
		yychar = -1
		yytoken = -1
		yyVAL = yylval
		yystate = yyn
		if Errflag > 0 {
			Errflag--
		}
		goto yystack
	}

yydefault:
	/* default state action */
	yyn = yyDef[yystate]
	if yyn == -2 {
		if yychar < 0 {
			yychar, yytoken = yylex1(yylex, &yylval)
		}

		/* look through exception table */
		xi := 0
		for {
			if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
				break
			}
			xi += 2
		}
		for xi += 2; ; xi += 2 {
			yyn = yyExca[xi+0]
			if yyn < 0 || yyn == yytoken {
				break
			}
		}
		yyn = yyExca[xi+1]
		if yyn < 0 {
			goto ret0
		}
	}
	if yyn == 0 {
		/* error ... attempt to resume parsing */
		switch Errflag {
		case 0: /* brand new error */
			yylex.Error(yyErrorMessage(yystate, yytoken))
			Nerrs++
			if yyDebug >= 1 {
				__yyfmt__.Printf("%s", yyStatname(yystate))
				__yyfmt__.Printf(" saw %s\n", yyTokname(yytoken))
			}
			fallthrough

		case 1, 2: /* incompletely recovered error ... try again */
			Errflag = 3

			/* find a state where "error" is a legal shift action */
			for yyp >= 0 {
				yyn = yyPact[yyS[yyp].yys] + yyErrCode
				if yyn >= 0 && yyn < yyLast {
					yystate = yyAct[yyn] /* simulate a shift of "error" */
					if yyChk[yystate] == yyErrCode {
						goto yystack
					}
				}

				/* the current p has no shift on "error", pop stack */
				if yyDebug >= 2 {
					__yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
				}
				yyp--
			}
			/* there is no state on the stack with an error shift ... abort */
			goto ret1

		case 3: /* no shift yet; clobber input char */
			if yyDebug >= 2 {
				__yyfmt__.Printf("error recovery discards %s\n", yyTokname(yytoken))
			}
			if yytoken == yyEofCode {
				goto ret1
			}
			yychar = -1
			yytoken = -1
			goto yynewstate /* try again in the same state */
		}
	}

	/* reduction by production yyn */
	if yyDebug >= 2 {
		__yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
	}

	yynt := yyn
	yypt := yyp
	_ = yypt // guard against "declared and not used"

	yyp -= yyR2[yyn]
	// yyp is now the index of $0. Perform the default action. Iff the
	// reduced production is ε, $1 is possibly out of range.
	if yyp+1 >= len(yyS) {
		nyys := make([]yySymType, len(yyS)*2)
		copy(nyys, yyS)
		yyS = nyys
	}
	yyVAL = yyS[yyp+1]

	/* consult goto table to find next state */
	yyn = yyR1[yyn]
	yyg := yyPgo[yyn]
	yyj := yyg + yyS[yyp].yys + 1

	if yyj >= yyLast {
		yystate = yyAct[yyg]
	} else {
		yystate = yyAct[yyj]
		if yyChk[yystate] != -yyn {
			yystate = yyAct[yyg]
		}
	}
	// dummy call; replaced with literal code
	switch yynt {

	case 2:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:73
		{
			stmtline = asm.Lineno
		}
	case 4:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:80
		{
			yyDollar[1].sym = asm.LabelLookup(yyDollar[1].sym)
			if yyDollar[1].sym.Type == LLAB && yyDollar[1].sym.Value != int64(asm.PC) {
				yyerror("redeclaration of %s", yyDollar[1].sym.Labelname)
			}
			yyDollar[1].sym.Type = LLAB
			yyDollar[1].sym.Value = int64(asm.PC)
		}
	case 6:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:90
		{
			yyDollar[1].sym.Type = LVAR
			yyDollar[1].sym.Value = int64(yyDollar[3].lval)
		}
	case 7:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:95
		{
			if yyDollar[1].sym.Value != int64(yyDollar[3].lval) {
				yyerror("redeclaration of %s", yyDollar[1].sym.Name)
			}
			yyDollar[1].sym.Value = int64(yyDollar[3].lval)
		}
	case 11:
		yyDollar = yyS[yypt-7 : yypt+1]
		//line a.y:110
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, yyDollar[5].lval, &yyDollar[7].addr)
		}
	case 12:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:114
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, yyDollar[5].lval, &nullgen)
		}
	case 13:
		yyDollar = yyS[yypt-5 : yypt+1]
		//line a.y:118
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, 0, &yyDollar[5].addr)
		}
	case 14:
		yyDollar = yyS[yypt-5 : yypt+1]
		//line a.y:125
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, 0, &yyDollar[5].addr)
		}
	case 15:
		yyDollar = yyS[yypt-5 : yypt+1]
		//line a.y:132
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, 0, &yyDollar[5].addr)
		}
	case 16:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:139
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &nullgen, 0, &yyDollar[4].addr)
		}
	case 17:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:143
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &nullgen, 0, &yyDollar[4].addr)
		}
	case 18:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:150
		{
			outcode(yyDollar[1].lval, Always, &nullgen, 0, &yyDollar[3].addr)
		}
	case 19:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:157
		{
			outcode(yyDollar[1].lval, Always, &nullgen, 0, &yyDollar[3].addr)
		}
	case 20:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:164
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &nullgen, 0, &yyDollar[4].addr)
		}
	case 21:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:171
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, yyDollar[5].lval, &nullgen)
		}
	case 22:
		yyDollar = yyS[yypt-7 : yypt+1]
		//line a.y:178
		{
			var g obj.Addr

			g = nullgen
			g.Type = obj.TYPE_REGLIST
			g.Offset = int64(yyDollar[6].lval)
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, 0, &g)
		}
	case 23:
		yyDollar = yyS[yypt-7 : yypt+1]
		//line a.y:187
		{
			var g obj.Addr

			g = nullgen
			g.Type = obj.TYPE_REGLIST
			g.Offset = int64(yyDollar[4].lval)
			outcode(yyDollar[1].lval, yyDollar[2].lval, &g, 0, &yyDollar[7].addr)
		}
	case 24:
		yyDollar = yyS[yypt-7 : yypt+1]
		//line a.y:199
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[5].addr, int32(yyDollar[3].addr.Reg), &yyDollar[7].addr)
		}
	case 25:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:203
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[5].addr, int32(yyDollar[3].addr.Reg), &yyDollar[3].addr)
		}
	case 26:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:207
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[4].addr, int32(yyDollar[6].addr.Reg), &yyDollar[6].addr)
		}
	case 27:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:214
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &nullgen, 0, &nullgen)
		}
	case 28:
		yyDollar = yyS[yypt-5 : yypt+1]
		//line a.y:221
		{
			asm.Settext(yyDollar[2].addr.Sym)
			outcode(yyDollar[1].lval, Always, &yyDollar[2].addr, 0, &yyDollar[5].addr)
			if asm.Pass > 1 {
				lastpc.From3 = new(obj.Addr)
			}
		}
	case 29:
		yyDollar = yyS[yypt-7 : yypt+1]
		//line a.y:229
		{
			asm.Settext(yyDollar[2].addr.Sym)
			outcode(yyDollar[1].lval, Always, &yyDollar[2].addr, 0, &yyDollar[7].addr)
			if asm.Pass > 1 {
				lastpc.From3 = new(obj.Addr)
				lastpc.From3.Type = obj.TYPE_CONST
				lastpc.From3.Offset = int64(yyDollar[4].lval)
			}
		}
	case 30:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:242
		{
			asm.Settext(yyDollar[2].addr.Sym)
			outcode(yyDollar[1].lval, Always, &yyDollar[2].addr, 0, &yyDollar[4].addr)
			if asm.Pass > 1 {
				lastpc.From3 = new(obj.Addr)
			}
		}
	case 31:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:250
		{
			asm.Settext(yyDollar[2].addr.Sym)
			outcode(yyDollar[1].lval, Always, &yyDollar[2].addr, 0, &yyDollar[6].addr)
			if asm.Pass > 1 {
				lastpc.From3 = new(obj.Addr)
				lastpc.From3.Type = obj.TYPE_CONST
				lastpc.From3.Offset = int64(yyDollar[4].lval)
			}
		}
	case 32:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:264
		{
			outcode(yyDollar[1].lval, Always, &yyDollar[2].addr, 0, &yyDollar[6].addr)
			if asm.Pass > 1 {
				lastpc.From3 = new(obj.Addr)
				lastpc.From3.Type = obj.TYPE_CONST
				lastpc.From3.Offset = int64(yyDollar[4].lval)
			}
		}
	case 33:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:276
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, 0, &nullgen)
		}
	case 34:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:283
		{
			outcode(yyDollar[1].lval, Always, &nullgen, 0, &yyDollar[3].addr)
		}
	case 35:
		yyDollar = yyS[yypt-5 : yypt+1]
		//line a.y:290
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, 0, &yyDollar[5].addr)
		}
	case 36:
		yyDollar = yyS[yypt-5 : yypt+1]
		//line a.y:294
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, 0, &yyDollar[5].addr)
		}
	case 37:
		yyDollar = yyS[yypt-7 : yypt+1]
		//line a.y:298
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, yyDollar[5].lval, &yyDollar[7].addr)
		}
	case 38:
		yyDollar = yyS[yypt-6 : yypt+1]
		//line a.y:302
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, int32(yyDollar[5].addr.Reg), &nullgen)
		}
	case 39:
		yyDollar = yyS[yypt-12 : yypt+1]
		//line a.y:309
		{
			var g obj.Addr

			g = nullgen
			g.Type = obj.TYPE_CONST
			g.Offset = int64(
				(0xe << 24) | /* opcode */
					(yyDollar[1].lval << 20) | /* MCR/MRC */
					((yyDollar[2].lval ^ C_SCOND_XOR) << 28) | /* scond */
					((yyDollar[3].lval & 15) << 8) | /* coprocessor number */
					((yyDollar[5].lval & 7) << 21) | /* coprocessor operation */
					((yyDollar[7].lval & 15) << 12) | /* arm register */
					((yyDollar[9].lval & 15) << 16) | /* Crn */
					((yyDollar[11].lval & 15) << 0) | /* Crm */
					((yyDollar[12].lval & 7) << 5) | /* coprocessor information */
					(1 << 4)) /* must be set */
			outcode(AMRC, Always, &nullgen, 0, &g)
		}
	case 40:
		yyDollar = yyS[yypt-7 : yypt+1]
		//line a.y:321
		{
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, int32(yyDollar[5].addr.Reg), &yyDollar[7].addr)
		}
	case 41:
		yyDollar = yyS[yypt-9 : yypt+1]
		//line a.y:329
		{
			yyDollar[7].addr.Type = obj.TYPE_REGREG2
			yyDollar[7].addr.Offset = int64(yyDollar[9].lval)
			outcode(yyDollar[1].lval, yyDollar[2].lval, &yyDollar[3].addr, int32(yyDollar[5].addr.Reg), &yyDollar[7].addr)
		}
	case 42:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:338
		{
			outcode(yyDollar[1].lval, Always, &yyDollar[2].addr, 0, &nullgen)
		}
	case 43:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:345
		{
			if yyDollar[2].addr.Type != obj.TYPE_CONST || yyDollar[4].addr.Type != obj.TYPE_CONST {
				yyerror("arguments to PCDATA must be integer constants")
			}
			outcode(yyDollar[1].lval, Always, &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 44:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:355
		{
			if yyDollar[2].addr.Type != obj.TYPE_CONST {
				yyerror("index for FUNCDATA must be integer constant")
			}
			if yyDollar[4].addr.Type != obj.NAME_EXTERN && yyDollar[4].addr.Type != obj.NAME_STATIC && yyDollar[4].addr.Type != obj.TYPE_MEM {
				yyerror("value for FUNCDATA must be symbol reference")
			}
			outcode(yyDollar[1].lval, Always, &yyDollar[2].addr, 0, &yyDollar[4].addr)
		}
	case 45:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:368
		{
			outcode(yyDollar[1].lval, Always, &nullgen, 0, &nullgen)
		}
	case 46:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:374
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_TEXTSIZE
			yyVAL.addr.Offset = int64(yyDollar[1].lval)
			yyVAL.addr.Val = int32(obj.ArgsSizeUnknown)
		}
	case 47:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:381
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_TEXTSIZE
			yyVAL.addr.Offset = -int64(yyDollar[2].lval)
			yyVAL.addr.Val = int32(obj.ArgsSizeUnknown)
		}
	case 48:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:388
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_TEXTSIZE
			yyVAL.addr.Offset = int64(yyDollar[1].lval)
			yyVAL.addr.Val = int32(yyDollar[3].lval)
		}
	case 49:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:395
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_TEXTSIZE
			yyVAL.addr.Offset = -int64(yyDollar[2].lval)
			yyVAL.addr.Val = int32(yyDollar[4].lval)
		}
	case 50:
		yyDollar = yyS[yypt-0 : yypt+1]
		//line a.y:403
		{
			yyVAL.lval = Always
		}
	case 51:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:407
		{
			yyVAL.lval = (yyDollar[1].lval & ^C_SCOND) | yyDollar[2].lval
		}
	case 52:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:411
		{
			yyVAL.lval = yyDollar[1].lval | yyDollar[2].lval
		}
	case 55:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:420
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_BRANCH
			yyVAL.addr.Offset = int64(yyDollar[1].lval) + int64(asm.PC)
		}
	case 56:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:426
		{
			yyDollar[1].sym = asm.LabelLookup(yyDollar[1].sym)
			yyVAL.addr = nullgen
			if asm.Pass == 2 && yyDollar[1].sym.Type != LLAB {
				yyerror("undefined label: %s", yyDollar[1].sym.Labelname)
			}
			yyVAL.addr.Type = obj.TYPE_BRANCH
			yyVAL.addr.Offset = yyDollar[1].sym.Value + int64(yyDollar[2].lval)
		}
	case 57:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:437
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_CONST
			yyVAL.addr.Offset = int64(yyDollar[2].lval)
		}
	case 58:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:443
		{
			yyVAL.addr = yyDollar[2].addr
			yyVAL.addr.Type = obj.TYPE_ADDR
		}
	case 59:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:448
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_SCONST
			yyVAL.addr.Val = yyDollar[2].sval
		}
	case 61:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:457
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_FCONST
			yyVAL.addr.Val = yyDollar[2].dval
		}
	case 62:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:463
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_FCONST
			yyVAL.addr.Val = -yyDollar[3].dval
		}
	case 63:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:471
		{
			yyVAL.lval = 1 << uint(yyDollar[1].lval&15)
		}
	case 64:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:475
		{
			yyVAL.lval = 0
			for i := yyDollar[1].lval; i <= yyDollar[3].lval; i++ {
				yyVAL.lval |= 1 << uint(i&15)
			}
			for i := yyDollar[3].lval; i <= yyDollar[1].lval; i++ {
				yyVAL.lval |= 1 << uint(i&15)
			}
		}
	case 65:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:485
		{
			yyVAL.lval = (1 << uint(yyDollar[1].lval&15)) | yyDollar[3].lval
		}
	case 69:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:494
		{
			yyVAL.addr = yyDollar[1].addr
			yyVAL.addr.Reg = int16(yyDollar[3].lval)
		}
	case 70:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:499
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 71:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:505
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 72:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:511
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Offset = int64(yyDollar[1].lval)
		}
	case 76:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:522
		{
			yyVAL.addr = yyDollar[1].addr
			if yyDollar[1].addr.Name != obj.NAME_EXTERN && yyDollar[1].addr.Name != obj.NAME_STATIC {
			}
		}
	case 77:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:530
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Reg = int16(yyDollar[2].lval)
			yyVAL.addr.Offset = 0
		}
	case 79:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:540
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Reg = int16(yyDollar[3].lval)
			yyVAL.addr.Offset = int64(yyDollar[1].lval)
		}
	case 81:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:550
		{
			yyVAL.addr = yyDollar[1].addr
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Reg = int16(yyDollar[3].lval)
		}
	case 86:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:563
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_CONST
			yyVAL.addr.Offset = int64(yyDollar[2].lval)
		}
	case 87:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:571
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 88:
		yyDollar = yyS[yypt-5 : yypt+1]
		//line a.y:579
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REGREG
			yyVAL.addr.Reg = int16(yyDollar[2].lval)
			yyVAL.addr.Offset = int64(yyDollar[4].lval)
		}
	case 89:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:588
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_SHIFT
			yyVAL.addr.Offset = int64(yyDollar[1].lval&15) | int64(yyDollar[4].lval) | (0 << 5)
		}
	case 90:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:594
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_SHIFT
			yyVAL.addr.Offset = int64(yyDollar[1].lval&15) | int64(yyDollar[4].lval) | (1 << 5)
		}
	case 91:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:600
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_SHIFT
			yyVAL.addr.Offset = int64(yyDollar[1].lval&15) | int64(yyDollar[4].lval) | (2 << 5)
		}
	case 92:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:606
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_SHIFT
			yyVAL.addr.Offset = int64(yyDollar[1].lval&15) | int64(yyDollar[4].lval) | (3 << 5)
		}
	case 93:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:614
		{
			if yyVAL.lval < REG_R0 || yyVAL.lval > REG_R15 {
				print("register value out of range\n")
			}
			yyVAL.lval = ((yyDollar[1].lval & 15) << 8) | (1 << 4)
		}
	case 94:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:621
		{
			if yyVAL.lval < 0 || yyVAL.lval >= 32 {
				print("shift value out of range\n")
			}
			yyVAL.lval = (yyDollar[1].lval & 31) << 7
		}
	case 96:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:631
		{
			yyVAL.lval = REGPC
		}
	case 97:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:635
		{
			if yyDollar[3].lval < 0 || yyDollar[3].lval >= NREG {
				print("register value out of range\n")
			}
			yyVAL.lval = REG_R0 + yyDollar[3].lval
		}
	case 99:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:645
		{
			yyVAL.lval = REGSP
		}
	case 101:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:652
		{
			if yyDollar[3].lval < 0 || yyDollar[3].lval >= NREG {
				print("register value out of range\n")
			}
			yyVAL.lval = yyDollar[3].lval // TODO(rsc): REG_C0+$3
		}
	case 104:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:665
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(yyDollar[1].lval)
		}
	case 105:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:671
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_REG
			yyVAL.addr.Reg = int16(REG_F0 + yyDollar[3].lval)
		}
	case 106:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:679
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Name = int8(yyDollar[3].lval)
			yyVAL.addr.Sym = nil
			yyVAL.addr.Offset = int64(yyDollar[1].lval)
		}
	case 107:
		yyDollar = yyS[yypt-5 : yypt+1]
		//line a.y:687
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Name = int8(yyDollar[4].lval)
			yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyDollar[1].sym.Name, 0)
			yyVAL.addr.Offset = int64(yyDollar[2].lval)
		}
	case 108:
		yyDollar = yyS[yypt-7 : yypt+1]
		//line a.y:695
		{
			yyVAL.addr = nullgen
			yyVAL.addr.Type = obj.TYPE_MEM
			yyVAL.addr.Name = obj.NAME_STATIC
			yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyDollar[1].sym.Name, 1)
			yyVAL.addr.Offset = int64(yyDollar[4].lval)
		}
	case 109:
		yyDollar = yyS[yypt-0 : yypt+1]
		//line a.y:704
		{
			yyVAL.lval = 0
		}
	case 110:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:708
		{
			yyVAL.lval = yyDollar[2].lval
		}
	case 111:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:712
		{
			yyVAL.lval = -yyDollar[2].lval
		}
	case 116:
		yyDollar = yyS[yypt-1 : yypt+1]
		//line a.y:724
		{
			yyVAL.lval = int32(yyDollar[1].sym.Value)
		}
	case 117:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:728
		{
			yyVAL.lval = -yyDollar[2].lval
		}
	case 118:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:732
		{
			yyVAL.lval = yyDollar[2].lval
		}
	case 119:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:736
		{
			yyVAL.lval = ^yyDollar[2].lval
		}
	case 120:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:740
		{
			yyVAL.lval = yyDollar[2].lval
		}
	case 121:
		yyDollar = yyS[yypt-0 : yypt+1]
		//line a.y:745
		{
			yyVAL.lval = 0
		}
	case 122:
		yyDollar = yyS[yypt-2 : yypt+1]
		//line a.y:749
		{
			yyVAL.lval = yyDollar[2].lval
		}
	case 124:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:756
		{
			yyVAL.lval = yyDollar[1].lval + yyDollar[3].lval
		}
	case 125:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:760
		{
			yyVAL.lval = yyDollar[1].lval - yyDollar[3].lval
		}
	case 126:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:764
		{
			yyVAL.lval = yyDollar[1].lval * yyDollar[3].lval
		}
	case 127:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:768
		{
			yyVAL.lval = yyDollar[1].lval / yyDollar[3].lval
		}
	case 128:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:772
		{
			yyVAL.lval = yyDollar[1].lval % yyDollar[3].lval
		}
	case 129:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:776
		{
			yyVAL.lval = yyDollar[1].lval << uint(yyDollar[4].lval)
		}
	case 130:
		yyDollar = yyS[yypt-4 : yypt+1]
		//line a.y:780
		{
			yyVAL.lval = yyDollar[1].lval >> uint(yyDollar[4].lval)
		}
	case 131:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:784
		{
			yyVAL.lval = yyDollar[1].lval & yyDollar[3].lval
		}
	case 132:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:788
		{
			yyVAL.lval = yyDollar[1].lval ^ yyDollar[3].lval
		}
	case 133:
		yyDollar = yyS[yypt-3 : yypt+1]
		//line a.y:792
		{
			yyVAL.lval = yyDollar[1].lval | yyDollar[3].lval
		}
	}
	goto yystack /* stack new state and value */
}