// 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) }
// 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 } }
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 }
// 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) }
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 }
// 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 }
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]) }
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] }
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 }
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] }
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++ }
// 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) }
// 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) }
// 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) }
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 }
// 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) } }
/* * 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 }
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 */ }
/* * 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 }
// 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) } } }
/* * 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 }
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) } }
func Addrconst(a *obj.Addr, v int64) { a.Sym = nil a.Type = obj.TYPE_CONST a.Offset = v }
// 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 }
/* * 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 }
/* * 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 }
// 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 }
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 */ }