ctxt->diag("%L: TLS MRC instruction must write to R0 as it might get translated into a BL instruction", p->lineno);
if(ctxt->goarm < 7) {
- // Replace it with BL runtime.read_tls_fallback(SB).
+ // Replace it with BL runtime.read_tls_fallback(SB) for ARM CPUs that lack the tls extension.
if(tlsfallback == nil)
tlsfallback = linklookup(ctxt, "runtime.read_tls_fallback", 0);
- // BL runtime.read_tls_fallback(SB)
+ // MOVW LR, R11
+ p->as = AMOVW;
+ p->from.type = D_REG;
+ p->from.reg = REGLINK;
+ p->to.type = D_REG;
+ p->to.reg = REGTMP;
+
+ // BL runtime.read_tls_fallback(SB)
+ p = appendp(ctxt, p);
p->as = ABL;
p->to.type = D_BRANCH;
p->to.sym = tlsfallback;
p->to.offset = 0;
+
+ // MOVW R11, LR
+ p = appendp(ctxt, p);
+ p->as = AMOVW;
+ p->from.type = D_REG;
+ p->from.reg = REGTMP;
+ p->to.type = D_REG;
+ p->to.reg = REGLINK;
break;
}
}
#endif
// If the host does not support MRC the linker will replace it with
// a call to runtime.read_tls_fallback which jumps to __kuser_get_tls.
- // Both functions are written to only disturb R0 so it should be safe to
- // use R11 here to temporarily store LR.
- MOVW LR, R11
+ // The replacement function saves LR in R11 over the call to read_tls_fallback.
MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
- MOVW R11, LR
// $runtime.tlsg(SB) is a special linker symbol.
// It is the offset from the TLS base pointer to our
// thread-local storage for g.
// nothing to do as nacl/arm does not use TLS at all.
RET
#endif
- // See comment in save_g.
- MOVW LR, R11
- MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
- MOVW R11, LR
+ // See save_g
+ MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
// $runtime.tlsg(SB) is a special linker symbol.
// It is the offset from the TLS base pointer to our
// thread-local storage for g.