#include #include #include #include int locfmt(Fmt *fmt) { Loc l; l = va_arg(fmt->args, Loc); switch(l.type){ default: return fmtprint(fmt, "", l.type); case LCONST: return fmtprint(fmt, "0x%lux", l.addr); case LADDR: return fmtprint(fmt, "*0x%lux", l.addr); case LOFFSET: return fmtprint(fmt, "%ld(%s)", l.offset, l.reg); case LREG: return fmtprint(fmt, "%s", l.reg); } } int loccmp(Loc *a, Loc *b) { int i; if(a->type < b->type) return -1; if(a->type > b->type) return 1; switch(a->type){ default: return 0; case LADDR: if(a->addr < b->addr) return -1; if(a->addr > b->addr) return 1; return 0; case LOFFSET: i = strcmp(a->reg, b->reg); if(i != 0) return i; if(a->offset < b->offset) return -1; if(a->offset > b->offset) return 1; return 0; case LREG: return strcmp(a->reg, b->reg); } } int lget1(Map *map, Regs *regs, Loc loc, uchar *a, uint n) { if(locsimplify(map, regs, loc, &loc) < 0) return -1; if(loc.type == LADDR) return get1(map, loc.addr, a, n); /* could do more here - i'm lazy */ werrstr("bad location for lget1"); return -1; } int lget2(Map *map, Regs *regs, Loc loc, u16int *u) { u64int ul; if(locsimplify(map, regs, loc, &loc) < 0) return -1; if(loc.type == LADDR) return get2(map, loc.addr, u); if(loc.type == LCONST){ *u = loc.addr; return 0; } if(loc.type == LREG){ if(rget(regs, loc.reg, &ul) < 0) return -1; *u = ul; return 0; } werrstr("bad location for lget2"); return -1; } int lget4(Map *map, Regs *regs, Loc loc, u32int *u) { u64int ul; if(locsimplify(map, regs, loc, &loc) < 0) return -1; if(loc.type == LADDR) return get4(map, loc.addr, u); if(loc.type == LCONST){ *u = loc.addr; return 0; } if(loc.type == LREG){ if(rget(regs, loc.reg, &ul) < 0) return -1; *u = ul; return 0; } werrstr("bad location for lget4"); return -1; } int lgeta(Map *map, Regs *regs, Loc loc, u64int *u) { u32int v; if(machcpu == &machamd64) return lget8(map, regs, loc, u); if(lget4(map, regs, loc, &v) < 0) return -1; *u = v; return 4; } int lget8(Map *map, Regs *regs, Loc loc, u64int *u) { u64int ul; if(locsimplify(map, regs, loc, &loc) < 0) return -1; if(loc.type == LADDR) return get8(map, loc.addr, u); if(loc.type == LCONST){ *u = loc.addr; return 0; } if(loc.type == LREG){ if(rget(regs, loc.reg, &ul) < 0) return -1; *u = ul; return 0; } werrstr("bad location for lget8"); return -1; } int lput1(Map *map, Regs *regs, Loc loc, uchar *a, uint n) { if(locsimplify(map, regs, loc, &loc) < 0) return -1; if(loc.type == LADDR) return put1(map, loc.addr, a, n); /* could do more here - i'm lazy */ werrstr("bad location for lput1"); return -1; } int lput2(Map *map, Regs *regs, Loc loc, u16int u) { if(locsimplify(map, regs, loc, &loc) < 0) return -1; if(loc.type == LADDR) return put2(map, loc.addr, u); if(loc.type == LREG) return rput(regs, loc.reg, u); werrstr("bad location for lput2"); return -1; } int lput4(Map *map, Regs *regs, Loc loc, u32int u) { if(locsimplify(map, regs, loc, &loc) < 0) return -1; if(loc.type == LADDR) return put4(map, loc.addr, u); if(loc.type == LREG) return rput(regs, loc.reg, u); werrstr("bad location for lput4"); return -1; } int lput8(Map *map, Regs *regs, Loc loc, u64int u) { if(locsimplify(map, regs, loc, &loc) < 0) return -1; if(loc.type == LADDR) return put8(map, loc.addr, u); if(loc.type == LREG) return rput(regs, loc.reg, u); werrstr("bad location for lput8"); return -1; } static Loc zl; Loc locaddr(u64int addr) { Loc l; l = zl; l.type = LADDR; l.addr = addr; return l; } Loc locindir(char *reg, long offset) { Loc l; l = zl; l.type = LOFFSET; l.reg = reg; l.offset = offset; l.addr = 0; /* SHUT UP GCC 4.0 */ return l; } Loc locconst(u64int con) { Loc l; l = zl; l.type = LCONST; l.addr = con; return l; } Loc locnone(void) { Loc l; l = zl; l.type = LNONE; return l; } Loc locreg(char *reg) { Loc l; l = zl; l.type = LREG; l.reg = reg; return l; } int locsimplify(Map *map, Regs *regs, Loc loc, Loc *newloc) { u64int u; if(loc.type == LOFFSET){ if(rget(regs, loc.reg, &u) < 0) return -1; *newloc = locaddr(u + loc.offset); }else *newloc = loc; return 0; }