func follow(ctxt *liblink.Link, s *liblink.LSym) { var firstp *liblink.Prog var lastp *liblink.Prog ctxt.Cursym = s firstp = ctxt.Prg() lastp = firstp xfol(ctxt, s.Text, &lastp) lastp.Link = nil s.Text = firstp.Link }
func xfol(ctxt *liblink.Link, p *liblink.Prog, last **liblink.Prog) { var q *liblink.Prog var r *liblink.Prog var a int var i int loop: if p == nil { return } a = p.As if a == AB { q = p.Pcond if q != nil && q.As != ATEXT { p.Mark |= FOLL p = q if p.Mark&FOLL == 0 { goto loop } } } if p.Mark&FOLL != 0 { i = 0 q = p for ; i < 4; (func() { i++; q = q.Link })() { if q == *last || q == nil { break } a = q.As if a == ANOP { i-- continue } if a == AB || (a == ARET && q.Scond == C_SCOND_NONE) || a == ARFE || a == AUNDEF { goto copy } if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) { continue } if a != ABEQ && a != ABNE { continue } copy: for { r = ctxt.Prg() *r = *p if r.Mark&FOLL == 0 { fmt.Printf("can't happen 1\n") } r.Mark |= FOLL if p != q { p = p.Link (*last).Link = r *last = r continue } (*last).Link = r *last = r if a == AB || (a == ARET && q.Scond == C_SCOND_NONE) || a == ARFE || a == AUNDEF { return } r.As = ABNE if a == ABNE { r.As = ABEQ } r.Pcond = p.Link r.Link = p.Pcond if r.Link.Mark&FOLL == 0 { xfol(ctxt, r.Link, last) } if r.Pcond.Mark&FOLL == 0 { fmt.Printf("can't happen 2\n") } return } } a = AB q = ctxt.Prg() q.As = a q.Lineno = p.Lineno q.To.Typ = D_BRANCH q.To.Offset = p.Pc q.Pcond = p p = q } p.Mark |= FOLL (*last).Link = p *last = p if a == AB || (a == ARET && p.Scond == C_SCOND_NONE) || a == ARFE || a == AUNDEF { return } if p.Pcond != nil { if a != ABL && a != ABX && p.Link != nil { q = liblink.Brchain(ctxt, p.Link) if a != ATEXT && a != ABCASE { if q != nil && (q.Mark&FOLL != 0) { p.As = relinv(a) p.Link = p.Pcond p.Pcond = q } } xfol(ctxt, p.Link, last) q = liblink.Brchain(ctxt, p.Pcond) if q == nil { q = p.Pcond } if q.Mark&FOLL != 0 { p.Pcond = q return } p = q goto loop } } p = p.Link goto loop }
func softfloat(ctxt *liblink.Link, cursym *liblink.LSym) { var p *liblink.Prog var next *liblink.Prog var symsfloat *liblink.LSym var wasfloat int if ctxt.Goarm > 5 { return } symsfloat = liblink.Linklookup(ctxt, "_sfloat", 0) wasfloat = 0 for p = cursym.Text; p != nil; p = p.Link { if p.Pcond != nil { p.Pcond.Mark |= LABEL } } for p = cursym.Text; p != nil; p = p.Link { switch p.As { case AMOVW: if p.To.Typ == D_FREG || p.From.Typ == D_FREG { goto soft } goto notsoft case AMOVWD, AMOVWF, AMOVDW, AMOVFW, AMOVFD, AMOVDF, AMOVF, AMOVD, ACMPF, ACMPD, AADDF, AADDD, ASUBF, ASUBD, AMULF, AMULD, ADIVF, ADIVD, ASQRTF, ASQRTD, AABSF, AABSD: goto soft default: goto notsoft } soft: if wasfloat == 0 || (p.Mark&LABEL != 0) { next = ctxt.Prg() *next = *p // BL _sfloat(SB) *p = zprg_obj5 p.Ctxt = ctxt p.Link = next p.As = ABL p.To.Typ = D_BRANCH p.To.Sym = symsfloat p.Lineno = next.Lineno p = next wasfloat = 1 } continue notsoft: wasfloat = 0 } }
func xfol(ctxt *liblink.Link, p *liblink.Prog, last **liblink.Prog) { var q *liblink.Prog var i int var a int loop: if p == nil { return } if p.As == AJMP { q = p.Pcond if q != nil && q.As != ATEXT { /* mark instruction as done and continue layout at target of jump */ p.Mark = 1 p = q if p.Mark == 0 { goto loop } } } if p.Mark != 0 { /* * p goes here, but already used it elsewhere. * copy up to 4 instructions or else branch to other copy. */ i = 0 q = p for ; i < 4; (func() { i++; q = q.Link })() { if q == nil { break } if q == *last { break } a = q.As if a == ANOP { i-- continue } if nofollow(a) || pushpop(a) != 0 { break // NOTE(rsc): arm does goto copy } if q.Pcond == nil || q.Pcond.Mark != 0 { continue } if a == ACALL || a == ALOOP { continue } for { if p.As == ANOP { p = p.Link continue } q = liblink.Copyp(ctxt, p) p = p.Link q.Mark = 1 (*last).Link = q *last = q if q.As != a || q.Pcond == nil || q.Pcond.Mark != 0 { continue } q.As = relinv(q.As) p = q.Pcond q.Pcond = q.Link q.Link = p xfol(ctxt, q.Link, last) p = q.Link if p.Mark != 0 { return } goto loop /* */ } } q = ctxt.Prg() q.As = AJMP q.Lineno = p.Lineno q.To.Typ = D_BRANCH q.To.Offset = p.Pc q.Pcond = p p = q } /* emit p */ p.Mark = 1 (*last).Link = p *last = p a = p.As /* continue loop with what comes after p */ if nofollow(a) { return } if p.Pcond != nil && a != ACALL { /* * some kind of conditional branch. * recurse to follow one path. * continue loop on the other. */ q = liblink.Brchain(ctxt, p.Pcond) if q != nil { p.Pcond = q } q = liblink.Brchain(ctxt, p.Link) if q != nil { p.Link = q } if p.From.Typ == D_CONST { if p.From.Offset == 1 { /* * expect conditional jump to be taken. * rewrite so that's the fall-through case. */ p.As = relinv(a) q = p.Link p.Link = p.Pcond p.Pcond = q } } else { q = p.Link if q.Mark != 0 { if a != ALOOP { p.As = relinv(a) p.Link = p.Pcond p.Pcond = q } } } xfol(ctxt, p.Link, last) if p.Pcond.Mark != 0 { return } p = p.Pcond goto loop } p = p.Link goto loop }