mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-15 11:20:03 +00:00
253 lines
3.9 KiB
C
253 lines
3.9 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <bio.h>
|
|
#include <mach.h>
|
|
|
|
int
|
|
locfmt(Fmt *fmt)
|
|
{
|
|
Loc l;
|
|
|
|
l = va_arg(fmt->args, Loc);
|
|
switch(l.type){
|
|
default:
|
|
return fmtprint(fmt, "<loc%d>", 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)
|
|
{
|
|
ulong 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)
|
|
{
|
|
ulong 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
|
|
lget8(Map *map, Regs *regs, Loc loc, u64int *u)
|
|
{
|
|
ulong 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;
|
|
}
|
|
|
|
Loc
|
|
locaddr(ulong addr)
|
|
{
|
|
Loc l;
|
|
|
|
l.type = LADDR;
|
|
l.addr = addr;
|
|
return l;
|
|
}
|
|
|
|
Loc
|
|
locindir(char *reg, long offset)
|
|
{
|
|
Loc l;
|
|
|
|
l.type = LOFFSET;
|
|
l.reg = reg;
|
|
l.offset = offset;
|
|
return l;
|
|
}
|
|
|
|
Loc
|
|
locconst(ulong con)
|
|
{
|
|
Loc l;
|
|
|
|
l.type = LCONST;
|
|
l.addr = con;
|
|
return l;
|
|
}
|
|
|
|
Loc
|
|
locnone(void)
|
|
{
|
|
Loc l;
|
|
|
|
l.type = LNONE;
|
|
return l;
|
|
}
|
|
|
|
Loc
|
|
locreg(char *reg)
|
|
{
|
|
Loc l;
|
|
|
|
l.type = LREG;
|
|
l.reg = reg;
|
|
return l;
|
|
}
|
|
|
|
int
|
|
locsimplify(Map *map, Regs *regs, Loc loc, Loc *newloc)
|
|
{
|
|
ulong u;
|
|
|
|
if(loc.type == LOFFSET){
|
|
if(rget(regs, loc.reg, &u) < 0)
|
|
return -1;
|
|
*newloc = locaddr(u + loc.offset);
|
|
}else
|
|
*newloc = loc;
|
|
return 0;
|
|
}
|
|
|