static void relput4(Prog *p, Adr *a) { vlong v; Reloc rel, *r; v = vaddr(a, &rel); if(rel.siz != 0) { if(rel.siz != 4) diag("bad reloc"); r = addrel(cursym); *r = rel; r->off = p->pc + andptr - and; } put4(v); }
vlong addsize(Sym *s, Sym *t) { vlong i; Reloc *r; if(s->type == 0) s->type = SDATA; s->reachable = 1; i = s->size; s->size += PtrSize; symgrow(s, s->size); r = addrel(s); r->sym = t; r->off = i; r->siz = PtrSize; r->type = D_SIZE; return i; }
vlong addpcrelplus(Sym *s, Sym *t, int32 add) { vlong i; Reloc *r; if(s->type == 0) s->type = SDATA; s->reachable = 1; i = s->size; s->size += 4; symgrow(s, s->size); r = addrel(s); r->sym = t; r->off = i; r->add = add; r->type = D_PCREL; r->siz = 4; return i; }
vlong addaddrplus(Sym *s, Sym *t, int32 add) { vlong i; Reloc *r; if(s->type == 0) s->type = SDATA; s->reachable = 1; i = s->size; s->size += PtrSize; symgrow(s, s->size); r = addrel(s); r->sym = t; r->off = i; r->siz = PtrSize; r->type = D_ADDR; r->add = add; return i; }
vlong setaddrplus(Sym *s, vlong off, Sym *t, int32 add) { Reloc *r; if(s->type == 0) s->type = SDATA; s->reachable = 1; if(off+PtrSize > s->size) { s->size = off + PtrSize; symgrow(s, s->size); } r = addrel(s); r->sym = t; r->off = off; r->siz = PtrSize; r->type = D_ADDR; r->add = add; return off; }
void savedata(Sym *s, Prog *p, char *pn) { int32 off, siz, i, fl; uchar *cast; vlong o; Reloc *r; off = p->from.offset; siz = p->datasize; if(off < 0 || siz < 0 || off >= 1<<30 || siz >= 100) mangle(pn); symgrow(s, off+siz); switch(p->to.type) { default: diag("bad data: %P", p); break; case D_FCONST: switch(siz) { default: case 4: fl = ieeedtof(&p->to.ieee); cast = (uchar*)&fl; for(i=0; i<4; i++) s->p[off+i] = cast[fnuxi4[i]]; break; case 8: cast = (uchar*)&p->to.ieee; for(i=0; i<8; i++) s->p[off+i] = cast[fnuxi8[i]]; break; } break; case D_SCONST: for(i=0; i<siz; i++) s->p[off+i] = p->to.scon[i]; break; case D_CONST: if(p->to.sym) goto Addr; o = p->to.offset; fl = o; cast = (uchar*)&fl; switch(siz) { default: diag("bad nuxi %d\n%P", siz, p); break; case 1: s->p[off] = cast[inuxi1[0]]; break; case 2: for(i=0; i<2; i++) s->p[off+i] = cast[inuxi2[i]]; break; case 4: for(i=0; i<4; i++) s->p[off+i] = cast[inuxi4[i]]; break; case 8: cast = (uchar*)&o; for(i=0; i<8; i++) s->p[off+i] = cast[inuxi8[i]]; break; } break; case D_ADDR: case D_SIZE: Addr: r = addrel(s); r->off = off; r->siz = siz; r->sym = p->to.sym; r->type = p->to.type; if(r->type != D_SIZE) r->type = D_ADDR; r->add = p->to.offset; break; } }
void asmand(Adr *a, int r) { int32 v; int t, scale; Reloc rel; v = a->offset; t = a->type; rel.siz = 0; if(a->index != D_NONE && a->index != D_FS && a->index != D_GS) { if(t < D_INDIR || t >= 2*D_INDIR) { switch(t) { default: goto bad; case D_STATIC: case D_EXTERN: t = D_NONE; v = vaddr(a, &rel); break; case D_AUTO: case D_PARAM: t = D_SP; break; } } else t -= D_INDIR; if(t == D_NONE) { *andptr++ = (0 << 6) | (4 << 0) | (r << 3); asmidx(a->scale, a->index, t); goto putrelv; } if(v == 0 && rel.siz == 0 && t != D_BP) { *andptr++ = (0 << 6) | (4 << 0) | (r << 3); asmidx(a->scale, a->index, t); return; } if(v >= -128 && v < 128 && rel.siz == 0) { *andptr++ = (1 << 6) | (4 << 0) | (r << 3); asmidx(a->scale, a->index, t); *andptr++ = v; return; } *andptr++ = (2 << 6) | (4 << 0) | (r << 3); asmidx(a->scale, a->index, t); goto putrelv; } if(t >= D_AL && t <= D_F7 || t >= D_X0 && t <= D_X7) { if(v) goto bad; *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3); return; } scale = a->scale; if(t < D_INDIR || t >= 2*D_INDIR) { switch(a->type) { default: goto bad; case D_STATIC: case D_EXTERN: t = D_NONE; v = vaddr(a, &rel); break; case D_AUTO: case D_PARAM: t = D_SP; break; } scale = 1; } else t -= D_INDIR; if(t == D_NONE || (D_CS <= t && t <= D_GS)) { *andptr++ = (0 << 6) | (5 << 0) | (r << 3); goto putrelv; } if(t == D_SP) { if(v == 0 && rel.siz == 0) { *andptr++ = (0 << 6) | (4 << 0) | (r << 3); asmidx(scale, D_NONE, t); return; } if(v >= -128 && v < 128 && rel.siz == 0) { *andptr++ = (1 << 6) | (4 << 0) | (r << 3); asmidx(scale, D_NONE, t); *andptr++ = v; return; } *andptr++ = (2 << 6) | (4 << 0) | (r << 3); asmidx(scale, D_NONE, t); goto putrelv; } if(t >= D_AX && t <= D_DI) { if(v == 0 && rel.siz == 0 && t != D_BP) { *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3); return; } if(v >= -128 && v < 128 && rel.siz == 0 && a->index != D_FS && a->index != D_GS) { andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3); andptr[1] = v; andptr += 2; return; } *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3); goto putrelv; } goto bad; putrelv: if(rel.siz != 0) { Reloc *r; if(rel.siz != 4) { diag("bad rel"); goto bad; } r = addrel(cursym); *r = rel; r->off = curp->pc + andptr - and; } else if(iself && linkmode == LinkExternal && istls(a) && HEADTYPE != Hopenbsd) { Reloc *r; Sym *s; r = addrel(cursym); r->off = curp->pc + andptr - and; r->add = a->offset-tlsoffset; r->xadd = r->add; r->siz = 4; r->type = D_TLS; s = lookup("runtime.tlsgm", 0); r->sym = s; r->xsym = s; v = 0; } put4(v); return; bad: diag("asmand: bad address %D", a); return; }
void asmand(Adr *a, int r) { int32 v; int t, scale; Reloc rel; v = a->offset; t = a->type; rel.siz = 0; if(a->index != D_NONE) { if(t < D_INDIR || t >= 2*D_INDIR) { switch(t) { default: goto bad; case D_STATIC: case D_EXTERN: t = D_NONE; v = vaddr(a, &rel); break; case D_AUTO: case D_PARAM: t = D_SP; break; } } else t -= D_INDIR; if(t == D_NONE) { *andptr++ = (0 << 6) | (4 << 0) | (r << 3); asmidx(a->scale, a->index, t); goto putrelv; } if(v == 0 && rel.siz == 0 && t != D_BP) { *andptr++ = (0 << 6) | (4 << 0) | (r << 3); asmidx(a->scale, a->index, t); return; } if(v >= -128 && v < 128 && rel.siz == 0) { *andptr++ = (1 << 6) | (4 << 0) | (r << 3); asmidx(a->scale, a->index, t); *andptr++ = v; return; } *andptr++ = (2 << 6) | (4 << 0) | (r << 3); asmidx(a->scale, a->index, t); goto putrelv; } if(t >= D_AL && t <= D_F7 || t >= D_X0 && t <= D_X7) { if(v) goto bad; *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3); return; } scale = a->scale; if(t < D_INDIR || t >= 2*D_INDIR) { switch(a->type) { default: goto bad; case D_STATIC: case D_EXTERN: t = D_NONE; v = vaddr(a, &rel); break; case D_AUTO: case D_PARAM: t = D_SP; break; } scale = 1; } else t -= D_INDIR; if(t == D_NONE || (D_CS <= t && t <= D_GS)) { *andptr++ = (0 << 6) | (5 << 0) | (r << 3); goto putrelv; } if(t == D_SP) { if(v == 0 && rel.siz == 0) { *andptr++ = (0 << 6) | (4 << 0) | (r << 3); asmidx(scale, D_NONE, t); return; } if(v >= -128 && v < 128 && rel.siz == 0) { *andptr++ = (1 << 6) | (4 << 0) | (r << 3); asmidx(scale, D_NONE, t); *andptr++ = v; return; } *andptr++ = (2 << 6) | (4 << 0) | (r << 3); asmidx(scale, D_NONE, t); goto putrelv; } if(t >= D_AX && t <= D_DI) { if(v == 0 && rel.siz == 0 && t != D_BP) { *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3); return; } if(v >= -128 && v < 128 && rel.siz == 0) { andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3); andptr[1] = v; andptr += 2; return; } *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3); goto putrelv; } goto bad; putrelv: if(rel.siz != 0) { Reloc *r; if(rel.siz != 4) { diag("bad rel"); goto bad; } r = addrel(cursym); *r = rel; r->off = curp->pc + andptr - and; } put4(v); return; bad: diag("asmand: bad address %D", a); return; }