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; }