func progedit(ctxt *liblink.Link, p *liblink.Prog) { var literal string var s *liblink.LSym var tlsfallback *liblink.LSym p.From.Class = 0 p.To.Class = 0 // Rewrite B/BL to symbol as D_BRANCH. switch p.As { case AB, ABL, ADUFFZERO, ADUFFCOPY: if p.To.Typ == D_OREG && (p.To.Name == D_EXTERN || p.To.Name == D_STATIC) && p.To.Sym != nil { p.To.Typ = D_BRANCH } break } // Replace TLS register fetches on older ARM procesors. switch p.As { // If the instruction matches MRC 15, 0, <reg>, C13, C0, 3, replace it. case AMRC: if ctxt.Goarm < 7 && p.To.Offset&0xffff0fff == 0xee1d0f70 { tlsfallback = liblink.Linklookup(ctxt, "runtime.read_tls_fallback", 0) // BL runtime.read_tls_fallback(SB) p.As = ABL p.To.Typ = D_BRANCH p.To.Sym = tlsfallback p.To.Offset = 0 } else { // Otherwise, MRC/MCR instructions need no further treatment. p.As = AWORD } break } // Rewrite float constants to values stored in memory. switch p.As { case AMOVF: if p.From.Typ == D_FCONST && chipfloat5(ctxt, p.From.U.Dval) < 0 && (chipzero5(ctxt, p.From.U.Dval) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) { var i32 uint32 var f32 float32 f32 = float32(p.From.U.Dval) i32 = math.Float32bits(f32) literal = fmt.Sprintf("$f32.%08x", i32) s = liblink.Linklookup(ctxt, literal, 0) if s.Typ == 0 { s.Typ = liblink.SRODATA liblink.Adduint32(ctxt, s, i32) s.Reachable = 0 } p.From.Typ = D_OREG p.From.Sym = s p.From.Name = D_EXTERN p.From.Offset = 0 } case AMOVD: if p.From.Typ == D_FCONST && chipfloat5(ctxt, p.From.U.Dval) < 0 && (chipzero5(ctxt, p.From.U.Dval) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) { var i64 uint64 i64 = math.Float64bits(p.From.U.Dval) literal = fmt.Sprintf("$f64.%016x", uint64(i64)) s = liblink.Linklookup(ctxt, literal, 0) if s.Typ == 0 { s.Typ = liblink.SRODATA liblink.Adduint64(ctxt, s, i64) s.Reachable = 0 } p.From.Typ = D_OREG p.From.Sym = s p.From.Name = D_EXTERN p.From.Offset = 0 } break } if ctxt.Flag_shared != 0 { // Shared libraries use R_ARM_TLS_IE32 instead of // R_ARM_TLS_LE32, replacing the link time constant TLS offset in // runtime.tlsg with an address to a GOT entry containing the // offset. Rewrite $runtime.tlsg(SB) to runtime.tlsg(SB) to // compensate. if ctxt.Tlsg == nil { ctxt.Tlsg = liblink.Linklookup(ctxt, "runtime.tlsg", 0) } if p.From.Typ == D_CONST && p.From.Name == D_EXTERN && p.From.Sym == ctxt.Tlsg { p.From.Typ = D_OREG } if p.To.Typ == D_CONST && p.To.Name == D_EXTERN && p.To.Sym == ctxt.Tlsg { p.To.Typ = D_OREG } } }