diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/vi |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/vi')
-rwxr-xr-x | sys/src/cmd/vi/bpt.c | 129 | ||||
-rwxr-xr-x | sys/src/cmd/vi/cmd.c | 649 | ||||
-rwxr-xr-x | sys/src/cmd/vi/float.c | 783 | ||||
-rwxr-xr-x | sys/src/cmd/vi/icache.c | 18 | ||||
-rwxr-xr-x | sys/src/cmd/vi/mem.c | 285 | ||||
-rwxr-xr-x | sys/src/cmd/vi/mips.h | 257 | ||||
-rwxr-xr-x | sys/src/cmd/vi/mkfile | 28 | ||||
-rwxr-xr-x | sys/src/cmd/vi/run.c | 869 | ||||
-rwxr-xr-x | sys/src/cmd/vi/special.c | 444 | ||||
-rwxr-xr-x | sys/src/cmd/vi/stats.c | 251 | ||||
-rwxr-xr-x | sys/src/cmd/vi/symbols.c | 96 | ||||
-rwxr-xr-x | sys/src/cmd/vi/syscall.c | 731 | ||||
-rwxr-xr-x | sys/src/cmd/vi/vi.c | 507 |
13 files changed, 5047 insertions, 0 deletions
diff --git a/sys/src/cmd/vi/bpt.c b/sys/src/cmd/vi/bpt.c new file mode 100755 index 000000000..ff6ef0b4c --- /dev/null +++ b/sys/src/cmd/vi/bpt.c @@ -0,0 +1,129 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include <ctype.h> +#define Extern extern +#include "mips.h" + +void +dobplist(void) +{ + Breakpoint *b; + char buf[512]; + + for(b = bplist; b; b = b->next) { + switch(b->type) { + case Instruction: + Bprint(bioout, "0x%lux,%d:b %d done, at ", b->addr, b->count, b->done); + symoff(buf, sizeof(buf), b->addr, CTEXT); + Bprint(bioout, buf); + break; + + case Access: + Bprint(bioout, "0x%lux,%d:ba %d done, at ", b->addr, b->count, b->done); + symoff(buf, sizeof(buf), b->addr, CDATA); + Bprint(bioout, buf); + break; + + case Read: + Bprint(bioout, "0x%lux,%d:br %d done, at ", b->addr, b->count, b->done); + symoff(buf, sizeof(buf), b->addr, CDATA); + Bprint(bioout, buf); + break; + + case Write: + Bprint(bioout, "0x%lux,%d:bw %d done, at ", b->addr, b->count, b->done); + symoff(buf, sizeof(buf), b->addr, CDATA); + Bprint(bioout, buf); + break; + + case Equal: + Bprint(bioout, "0x%lux,%d:be at ", b->addr, b->count); + symoff(buf, sizeof(buf), b->addr, CDATA); + Bprint(bioout, buf); + break; + } + Bprint(bioout, "\n"); + } +} + +void +breakpoint(char *addr, char *cp) +{ + Breakpoint *b; + int type; + + cp = nextc(cp); + type = Instruction; + switch(*cp) { + case 'r': + membpt++; + type = Read; + break; + case 'a': + membpt++; + type = Access; + break; + case 'w': + membpt++; + type = Write; + break; + case 'e': + membpt++; + type = Equal; + break; + } + b = emalloc(sizeof(Breakpoint)); + b->addr = expr(addr); + b->type = type; + b->count = cmdcount; + b->done = cmdcount; + + b->next = bplist; + bplist = b; +} + +void +delbpt(char *addr) +{ + Breakpoint *b, **l; + ulong baddr; + + baddr = expr(addr); + l = &bplist; + for(b = *l; b; b = b->next) { + if(b->addr == baddr) { + if(b->type != Instruction) + membpt++; + *l = b->next; + free(b); + return; + } + l = &b->next; + } + + Bprint(bioout, "no breakpoint\n"); +} + +void +brkchk(ulong addr, int type) +{ + Breakpoint *b; + + for(b = bplist; b; b = b->next) { + if(b->addr == addr && (b->type&type)) { + if(b->type == Equal && getmem_4(addr) == b->count) { + count = 1; + atbpt = 1; + return; + } + if(--b->done == 0) { + b->done = b->count; + count = 1; + atbpt = 1; + return; + } + } + } +} diff --git a/sys/src/cmd/vi/cmd.c b/sys/src/cmd/vi/cmd.c new file mode 100755 index 000000000..f54fe3763 --- /dev/null +++ b/sys/src/cmd/vi/cmd.c @@ -0,0 +1,649 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include <ctype.h> +#define Extern extern +#include "mips.h" + +char buf[128], lastcmd[128]; +char fmt = 'X'; +int width = 60; +int inc; + +ulong expr(char*); +ulong expr1(char*); +char* term(char*, ulong*); + +char * +nextc(char *p) +{ + while(*p && (*p == ' ' || *p == '\t') && *p != '\n') + p++; + + if(*p == '\n') + *p = '\0'; + + return p; +} + +char * +numsym(char *addr, ulong *val) +{ + char tsym[128], *t; + static char *delim = "`'<>/\\@*|-~+-/=?\n"; + Symbol s; + char c; + + t = tsym; + while(c = *addr) { + if(strchr(delim, c)) + break; + *t++ = c; + addr++; + } + t[0] = '\0'; + + if(strcmp(tsym, ".") == 0) { + *val = dot; + return addr; + } + + if(lookup(0, tsym, &s)) + *val = s.value; + else { + if(tsym[0] == '#') + *val = strtoul(tsym+1, 0, 16); + else + *val = strtoul(tsym, 0, 0); + } + return addr; +} + +ulong +expr(char *addr) +{ + ulong t, t2; + char op; + + if(*addr == '\0') + return dot; + + addr = numsym(addr, &t); + + if(*addr == '\0') + return t; + + addr = nextc(addr); + op = *addr++; + numsym(addr, &t2); + switch(op) { + default: + Bprint(bioout, "expr syntax\n"); + return 0; + case '+': + t += t2; + break; + case '-': + t -= t2; + break; + case '%': + t /= t2; + break; + case '&': + t &= t2; + break; + case '|': + t |= t2; + break; + } + + return t; +} + +int +buildargv(char *str, char **args, int max) +{ + int na = 0; + + while (na < max) { + while((*str == ' ' || *str == '\t' || *str == '\n') && *str != '\0') + str++; + + if(*str == '\0') + return na; + + args[na++] = str; + while(!(*str == ' ' || *str == '\t'|| *str == '\n') && *str != '\0') + str++; + + if(*str == '\n') + *str = '\0'; + + if(*str == '\0') + break; + + *str++ = '\0'; + } + return na; +} + +void +colon(char *addr, char *cp) +{ + int argc; + char *argv[100]; + char tbuf[512]; + + cp = nextc(cp); + switch(*cp) { + default: + Bprint(bioout, "?\n"); + return; + case 'b': + breakpoint(addr, cp+1); + return; + + case 'd': + delbpt(addr); + return; + + /* These fall through to print the stopped address */ + case 'r': + reset(); + argc = buildargv(cp+1, argv, 100); + initstk(argc, argv); + count = 0; + atbpt = 0; + run(); + break; + case 'c': + count = 0; + atbpt = 0; + run(); + break; + case 's': + cp = nextc(cp+1); + count = 0; + if(*cp) + count = strtoul(cp, 0, 0); + if(count == 0) + count = 1; + atbpt = 0; + run(); + break; + } + + dot = reg.pc; + Bprint(bioout, "%s at #%lux ", atbpt ? "breakpoint" : "stopped", dot); + symoff(tbuf, sizeof(tbuf), dot, CTEXT); + Bprint(bioout, tbuf); + if(fmt == 'z') + printsource(dot); + + Bprint(bioout, "\n"); +} + + +void +dollar(char *cp) +{ + int nr; + + cp = nextc(cp); + switch(*cp) { + default: + Bprint(bioout, "?\n"); + break; + + case 'c': + stktrace(*cp); + break; + + case 'C': + stktrace(*cp); + break; + + case 'b': + dobplist(); + break; + + case 'r': + dumpreg(); + break; + + case 'R': + dumpreg(); + + case 'f': + dumpfreg(); + break; + + case 'F': + dumpdreg(); + break; + + case 'q': + exits(0); + break; + + case 'Q': + isum(); + tlbsum(); + segsum(); + break; + + case 't': + cp++; + switch(*cp) { + default: + Bprint(bioout, "$t[0sicr#]\n"); + break; + case '\0': + trace = 1; + break; + case '0': + trace = 0; + sysdbg = 0; + calltree = 0; + break; + case 's': + sysdbg = 1; + break; + case 'i': + trace = 1; + break; + case 'c': + calltree = 1; + break; + case 'r': + nr = atoi(cp+1); + if(nr < 0 || nr > 31) { + print("bad register\n"); + break; + } + rtrace ^= (1<<nr); + print("%.8ux\n", rtrace); + break; + } + break; + + case 'i': + cp++; + switch(*cp) { + default: + Bprint(bioout, "$i[itsa]\n"); + break; + case 'i': + isum(); + break; + case 't': + tlbsum(); + break; + case 's': + segsum(); + break; + case 'a': + isum(); + tlbsum(); + segsum(); + iprofile(); + break; + case 'p': + iprofile(); + break; + } + } +} + +int +pfmt(char fmt, int mem, ulong val) +{ + int c, i; + Symbol s; + char *p, ch, str[1024]; + + c = 0; + switch(fmt) { + default: + Bprint(bioout, "bad modifier\n"); + return 0; + case 'o': + c = Bprint(bioout, "%-4lo ", mem ? (ushort)getmem_2(dot) : val); + inc = 2; + break; + + case 'O': + c = Bprint(bioout, "%-8lo ", mem ? getmem_4(dot) : val); + inc = 4; + break; + + case 'q': + c = Bprint(bioout, "%-4lo ", mem ? (short)getmem_2(dot) : val); + inc = 2; + break; + + case 'Q': + c = Bprint(bioout, "%-8lo ", mem ? (long)getmem_4(dot) : val); + inc = 4; + break; + + case 'd': + c = Bprint(bioout, "%-5ld ", mem ? (short)getmem_2(dot) : val); + inc = 2; + break; + + + case 'D': + c = Bprint(bioout, "%-8ld ", mem ? (long)getmem_4(dot) : val); + inc = 4; + break; + + case 'x': + c = Bprint(bioout, "#%-4lux ", mem ? (long)getmem_2(dot) : val); + inc = 2; + break; + + case 'X': + c = Bprint(bioout, "#%-8lux ", mem ? (long)getmem_4(dot) : val); + inc = 4; + break; + + case 'u': + c = Bprint(bioout, "%-5ld ", mem ? (ushort)getmem_2(dot) : val); + inc = 2; + break; + + case 'U': + c = Bprint(bioout, "%-8ld ", mem ? (ulong)getmem_4(dot) : val); + inc = 4; + break; + + case 'b': + c = Bprint(bioout, "%-3ld ", mem ? getmem_b(dot) : val); + inc = 1; + break; + + case 'c': + c = Bprint(bioout, "%c ", (int)(mem ? getmem_b(dot) : val)); + inc = 1; + break; + + case 'C': + ch = mem ? getmem_b(dot) : val; + if(isprint(ch)) + c = Bprint(bioout, "%c ", ch); + else + c = Bprint(bioout, "\\x%.2x ", ch); + inc = 1; + break; + + case 's': + i = 0; + while(ch = getmem_b(dot+i)) + str[i++] = ch; + str[i] = '\0'; + dot += i; + c = Bprint(bioout, "%s", str); + inc = 0; + break; + + case 'S': + i = 0; + while(ch = getmem_b(dot+i)) + str[i++] = ch; + str[i] = '\0'; + dot += i; + for(p = str; *p; p++) + if(isprint(*p)) + c += Bprint(bioout, "%c", *p); + else + c += Bprint(bioout, "\\x%.2ux", *p); + inc = 0; + break; + + case 'Y': + p = ctime(mem ? getmem_b(dot) : val); + p[30] = '\0'; + c = Bprint(bioout, "%s", p); + inc = 4; + break; + + case 'a': + symoff(str, sizeof(str), dot, CTEXT); + c = Bprint(bioout, str); + inc = 0; + break; + + case 'e': + for (i = 0; globalsym(&s, i); i++) + Bprint(bioout, "%-15s #%lux\n", s.name, getmem_4(s.value)); + inc = 0; + break; + + case 'i': + inc = _mipscoinst(symmap, dot, str, sizeof(str)); + if (inc < 0) { + Bprint(bioout, "vi: %r\n"); + return 0; + } + c = Bprint(bioout, str); + break; + + case 'n': + c = width+1; + inc = 0; + break; + + case '-': + c = 0; + inc = -1; + break; + + case '+': + c = 0; + inc = 1; + break; + + case '^': + c = 0; + if(inc > 0) + inc = -inc; + break; + + case 'z': + if (findsym(dot, CTEXT, &s)) + Bprint(bioout, " %s() ", s.name); + printsource(dot); + inc = 0; + break; + } + return c; +} + +void +eval(char *addr, char *p) +{ + ulong val; + + val = expr(addr); + p = nextc(p); + if(*p == '\0') { + p[0] = fmt; + p[1] = '\0'; + } + pfmt(*p, 0, val); + Bprint(bioout, "\n"); +} + +void +quesie(char *p) +{ + int c, count, i; + char tbuf[512]; + + c = 0; + symoff(tbuf, sizeof(tbuf), dot, CTEXT); + Bprint(bioout, "%s?\t", tbuf); + + while(*p) { + p = nextc(p); + if(*p == '"') { + for(p++; *p && *p != '"'; p++) { + Bputc(bioout, *p); + c++; + } + if(*p) + p++; + continue; + } + count = 0; + while(*p >= '0' && *p <= '9') + count = count*10 + (*p++ - '0'); + if(count == 0) + count = 1; + p = nextc(p); + if(*p == '\0') { + p[0] = fmt; + p[1] = '\0'; + } + for(i = 0; i < count; i++) { + c += pfmt(*p, 1, 0); + dot += inc; + if(c > width) { + Bprint(bioout, "\n"); + symoff(tbuf, sizeof(tbuf), dot, CTEXT); + Bprint(bioout, "%s?\t", tbuf); + c = 0; + } + } + fmt = *p++; + p = nextc(p); + } + Bprint(bioout, "\n"); +} + +void +catcher(void *a, char *msg) +{ + USED(a); + if(strcmp(msg, "interrupt") != 0) + noted(NDFLT); + + count = 1; + print("vi\n"); + noted(NCONT); +} + +void +setreg(char *addr, char *cp) +{ + int rn; + + dot = expr(addr); + cp = nextc(cp); + if(strcmp(cp, "pc") == 0) { + reg.pc = dot; + return; + } + if(strcmp(cp, "sp") == 0) { + reg.r[29] = dot; + return; + } + if(strcmp(cp, "mh") == 0) { + reg.mhi = dot; + return; + } + if(strcmp(cp, "ml") == 0) { + reg.mlo = dot; + return; + } + if(*cp++ == 'r') { + rn = strtoul(cp, 0, 10); + if(rn > 0 && rn < 32) { + reg.r[rn] = dot; + return; + } + } + Bprint(bioout, "bad register\n"); +} + +void +cmd(void) +{ + char *p, *a, *cp, *gotint; + char addr[128]; + static char *cmdlet = ":$?/=>"; + int n, i; + + notify(catcher); + + dot = reg.pc; + setjmp(errjmp); + + for(;;) { + Bflush(bioout); + p = buf; + n = 0; + for(;;) { + i = Bgetc(bin); + if(i < 0) + exits(0); + *p++ = i; + n++; + if(i == '\n') + break; + } + + if(buf[0] == '\n') + strcpy(buf, lastcmd); + else { + buf[n-1] = '\0'; + strcpy(lastcmd, buf); + } + p = buf; + a = addr; + + for(;;) { + p = nextc(p); + if(*p == 0 || strchr(cmdlet, *p)) + break; + *a++ = *p++; + } + + *a = '\0'; + cmdcount = 1; + cp = strchr(addr, ','); + if(cp != 0) { + if(cp[1] == '#') + cmdcount = strtoul(cp+2, &gotint, 16); + else + cmdcount = strtoul(cp+1, &gotint, 0); + *cp = '\0'; + } + + switch(*p) { + case '$': + dollar(p+1); + break; + case ':': + colon(addr, p+1); + break; + case '/': + case '?': + dot = expr(addr); + for(i = 0; i < cmdcount; i++) + quesie(p+1); + break; + case '=': + eval(addr, p+1); + break; + case '>': + setreg(addr, p+1); + break; + default: + Bprint(bioout, "?\n"); + break; + } + } +} diff --git a/sys/src/cmd/vi/float.c b/sys/src/cmd/vi/float.c new file mode 100755 index 000000000..8f1bbaf97 --- /dev/null +++ b/sys/src/cmd/vi/float.c @@ -0,0 +1,783 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "mips.h" + +void unimp(ulong); +void Ifcmp(ulong); +void Ifdiv(ulong); +void Ifmul(ulong); +void Ifadd(ulong); +void Ifsub(ulong); +void Ifmov(ulong); +void Icvtd(ulong); +void Icvtw(ulong); +void Icvts(ulong); +void Ifabs(ulong); +void Ifneg(ulong); + +Inst cop1[] = { + { Ifadd, "add.f", Ifloat }, + { Ifsub, "sub.f", Ifloat }, + { Ifmul, "mul.f", Ifloat }, + { Ifdiv, "div.f", Ifloat }, + { unimp, "", }, + { Ifabs, "abs.f", Ifloat }, + { Ifmov, "mov.f", Ifloat }, + { Ifneg, "neg.f", Ifloat }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { Icvts, "cvt.s", Ifloat }, + { Icvtd, "cvt.d", Ifloat }, + { unimp, "", }, + { unimp, "", }, + { Icvtw, "cvt.w", Ifloat }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { Ifcmp, "c.f", Ifloat }, + { Ifcmp, "c.un", Ifloat }, + { Ifcmp, "c.eq", Ifloat }, + { Ifcmp, "c.ueq", Ifloat }, + { Ifcmp, "c.olt", Ifloat }, + { Ifcmp, "c.ult", Ifloat }, + { Ifcmp, "c.ole", Ifloat }, + { Ifcmp, "c.ule", Ifloat }, + { Ifcmp, "c,sf", Ifloat }, + { Ifcmp, "c.ngle",Ifloat }, + { Ifcmp, "c.seq", Ifloat }, + { Ifcmp, "c.ngl", Ifloat }, + { Ifcmp, "c.lt", Ifloat }, + { Ifcmp, "c.nge", Ifloat }, + { Ifcmp, "c.le", Ifloat }, + { Ifcmp, "c.ngt", Ifloat }, + { 0 } +}; + +void +unimp(ulong inst) +{ + print("op %ld\n", inst&0x3f); + Bprint(bioout, "Unimplemented floating point Trap IR %.8lux\n", inst); + longjmp(errjmp, 0); +} + +void +inval(ulong inst) +{ + Bprint(bioout, "Invalid Operation Exception IR %.8lux\n", inst); + longjmp(errjmp, 0); +} + +void +ifmt(int r) +{ + Bprint(bioout, "Invalid Floating Data Format f%d pc 0x%lux\n", r, reg.pc); + longjmp(errjmp, 0); +} + +void +floatop(int dst, int s1, int s2) +{ + if(reg.ft[s1] == FPd && s1 != 24) + ifmt(s1); + if(reg.ft[s2] == FPd && s2 != 24) + ifmt(s2); + reg.ft[dst] = FPs; +} + +void +doubop(int dst, int s1, int s2) +{ + ulong l; + + if(reg.ft[s1] != FPd) { + if(reg.ft[s1] == FPs && s1 != 24) + ifmt(s1); + l = reg.di[s1]; + reg.di[s1] = reg.di[s1+1]; + reg.di[s1+1] = l; + reg.ft[s1] = FPd; + } + if(reg.ft[s2] != FPd) { + if(reg.ft[s2] == FPs && s2 != 24) + ifmt(s2); + l = reg.di[s2]; + reg.di[s2] = reg.di[s2+1]; + reg.di[s2+1] = l; + reg.ft[s2] = FPd; + } + reg.ft[dst] = FPd; +} + +void +Iswc1(ulong inst) +{ + int off; + ulong l; + int rt, rb, ert; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + if(trace) + itrace("swc1\tf%d,0x%x(r%d) ea=%lux", rt, off, rb, reg.r[rb]+off); + + ert = rt&~1; + if(reg.ft[ert] == FPd) { + l = reg.di[ert]; + reg.di[ert] = reg.di[ert+1]; + reg.di[ert+1] = l; + reg.ft[ert] = FPmemory; + } + putmem_w(reg.r[rb]+off, reg.di[rt]); +} + +void +Ifsub(ulong ir) +{ + char fmt; + int fs, ft, fd; + + Getf3(fs, ft, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, ft); + reg.fl[fd] = reg.fl[fs] - reg.fl[ft]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, ft); + reg.fd[fd>>1] = reg.fd[fs>>1] - reg.fd[ft>>1]; + break; + case 4: + fmt = 'w'; + reg.di[fd] = reg.di[fs] - reg.di[ft]; + break; + } + if(trace) + itrace("sub.%c\tf%d,f%d,f%d", fmt, fd, fs, ft); +} + +void +Ifmov(ulong ir) +{ + char fmt; + int fs, fd; + + Getf2(fs, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + reg.fl[fd] = reg.fl[fs]; + reg.ft[fd] = reg.ft[fs]; + break; + case 1: /* double */ + fmt = 'd'; + reg.fd[fd>>1] = reg.fd[fs>>1]; + reg.ft[fd] = reg.ft[fs]; + break; + case 4: + fmt = 'w'; + reg.di[fd] = reg.di[fs]; + reg.ft[fd] = reg.ft[fs]; + break; + } + if(trace) + itrace("mov.%c\tf%d,f%d", fmt, fd, fs); +} + +void +Ifabs(ulong ir) +{ + char fmt; + int fs, fd; + + Getf2(fs, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, fs); + if(reg.fl[fs] < 0.0) + reg.fl[fd] = -reg.fl[fs]; + else + reg.fl[fd] = reg.fl[fs]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, fs); + if(reg.fd[fs>>1] < 0.0) + reg.fd[fd>>1] = -reg.fd[fs>>1]; + else + reg.fd[fd>>1] = reg.fd[fs>>1]; + break; + case 4: + fmt = 'w'; + if((long)reg.di[fs] < 0) + reg.di[fd] = -reg.di[fs]; + else + reg.di[fd] = reg.di[fs]; + break; + } + if(trace) + itrace("abs.%c\tf%d,f%d", fmt, fd, fs); +} + +void +Ifneg(ulong ir) +{ + char fmt; + int fs, fd; + + Getf2(fs, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, fs); + reg.fl[fd] = -reg.fl[fs]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, fs); + reg.fd[fd>>1] = -reg.fd[fs>>1]; + break; + case 4: + fmt = 'w'; + reg.di[fd] = -reg.di[fs]; + break; + } + if(trace) + itrace("neg.%c\tf%d,f%d", fmt, fd, fs); +} + +void +Icvtd(ulong ir) +{ + char fmt; + int fs, fd; + + Getf2(fs, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fs, fs, fs); + reg.fd[fd>>1] = reg.fl[fs]; + reg.ft[fd] = FPd; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, fs); + reg.fd[fd>>1] = reg.fd[fs>>1]; + break; + case 4: + fmt = 'w'; + reg.fd[fd>>1] = (long)reg.di[fs]; + reg.ft[fd] = FPd; + break; + } + if(trace) + itrace("cvt.d.%c\tf%d,f%d", fmt, fd, fs); +} + +void +Icvts(ulong ir) +{ + char fmt; + int fs, fd; + + Getf2(fs, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, fs); + reg.fl[fd] = reg.fl[fs]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fs, fs, fs); + reg.fl[fd] = reg.fd[fs>>1]; + reg.ft[fd] = FPs; + break; + case 4: + fmt = 'w'; + reg.fl[fd] = (long)reg.di[fs]; + reg.ft[fd] = FPs; + break; + } + if(trace) + itrace("cvt.s.%c\tf%d,f%d", fmt, fd, fs); +} + +void +Icvtw(ulong ir) +{ + long v; + char fmt; + int fs, fd; + + Getf2(fs, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fs, fs, fs); + v = reg.fl[fs]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fs, fs, fs); + v = reg.fd[fs>>1]; + break; + case 4: + fmt = 'w'; + v = reg.di[fs]; + break; + } + reg.di[fd] = v; + reg.ft[fd] = FPmemory; + if(trace) + itrace("cvt.w.%c\tf%d,f%d", fmt, fd, fs); +} + +void +Ifadd(ulong ir) +{ + char fmt; + int fs, ft, fd; + + Getf3(fs, ft, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, ft); + reg.fl[fd] = reg.fl[fs] + reg.fl[ft]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, ft); + reg.fd[fd>>1] = reg.fd[fs>>1] + reg.fd[ft>>1]; + break; + case 4: + fmt = 'w'; + reg.di[fd] = reg.di[fs] + reg.di[ft]; + break; + } + if(trace) + itrace("add.%c\tf%d,f%d,f%d", fmt, fd, fs, ft); +} + +void +Ifmul(ulong ir) +{ + char fmt; + int fs, ft, fd; + + Getf3(fs, ft, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, ft); + reg.fl[fd] = reg.fl[fs] * reg.fl[ft]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, ft); + reg.fd[fd>>1] = reg.fd[fs>>1] * reg.fd[ft>>1]; + break; + case 4: + fmt = 'w'; + reg.di[fd] = reg.di[fs] * reg.di[ft]; + break; + } + if(trace) + itrace("mul.%c\tf%d,f%d,f%d", fmt, fd, fs, ft); +} + +void +Ifdiv(ulong ir) +{ + char fmt; + int fs, ft, fd; + + Getf3(fs, ft, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, ft); + reg.fl[fd] = reg.fl[fs] / reg.fl[ft]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, ft); + reg.fd[fd>>1] = reg.fd[fs>>1] / reg.fd[ft>>1]; + break; + case 4: + fmt = 'w'; + reg.di[fd] = reg.di[fs] / reg.di[ft]; + break; + } + if(trace) + itrace("div.%c\tf%d,f%d,f%d", fmt, fd, fs, ft); +} + +void +Ilwc1(ulong inst) +{ + int rt, rb; + int off; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + if(trace) + itrace("lwc1\tf%d,0x%x(r%d) ea=%lux", rt, off, rb, reg.r[rb]+off); + + reg.di[rt] = getmem_w(reg.r[rb]+off); + reg.ft[rt] = FPmemory; +} + +void +Ibcfbct(ulong inst) +{ + int takeit; + int off; + ulong npc; + + off = (short)(inst&0xffff); + + takeit = 0; + npc = reg.pc + (off<<2) + 4; + if(inst&(1<<16)) { + if(trace) + itrace("bc1t\t0x%lux", npc); + + if(reg.fpsr&FP_CBIT) + takeit = 1; + } + else { + if(trace) + itrace("bc1f\t0x%lux", npc); + + if((reg.fpsr&FP_CBIT) == 0) + takeit = 1; + } + + if(takeit) { + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + reg.pc = npc-4; + } +} + +void +Imtct(ulong ir) +{ + int rt, fs; + + SpecialGetrtrd(rt, fs, ir); + if(ir&(1<<22)) { /* CT */ + if(trace) + itrace("ctc1\tr%d,f%d", rt, fs); + } + else { /* MT */ + if(trace) + itrace("mtc1\tr%d,f%d", rt, fs); + + reg.di[fs] = reg.r[rt]; + reg.ft[fs] = FPmemory; + } +} + +void +Imfcf(ulong ir) +{ + int rt, fs; + + SpecialGetrtrd(rt, fs, ir); + if(ir&(1<<22)) { /* CF */ + if(trace) + itrace("cfc1\tr%d,f%d", rt, fs); + } + else { /* MF */ + if(trace) + itrace("mfc1\tr%d,f%d", rt, fs); + + reg.r[rt] = reg.di[fs]; + } +} + +void +Icop1(ulong ir) +{ + Inst *i; + + switch((ir>>23)&7) { + case 0: + Imfcf(ir); + break; + case 1: + Imtct(ir); + break; + case 2: + case 3: + Ibcfbct(ir); + break; + case 4: + case 5: + case 6: + case 7: + i = &cop1[ir&0x3f]; + i->count++; + (*i->func)(ir); + } +} + +void +Ifcmp(ulong ir) +{ + char fmt; + int fc; + int ft, fs; + + SpecialGetrtrd(ft, fs, ir); + + SET(fc); + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fs, fs, ft); + if(isNaN(reg.fl[fs]) || isNaN(reg.fl[ft])) { + fc = FP_U; + break; + } + if(reg.fl[fs] == reg.fl[ft]) { + fc = FP_E; + break; + } + if(reg.fl[fs] < reg.fl[ft]) { + fc = FP_L; + break; + } + if(reg.fl[fs] > reg.fl[ft]) { + fc = FP_G; + break; + } + print("vi: bad in fcmp"); + break; + case 1: /* double */ + fmt = 'd'; + doubop(fs, fs, ft); + if(isNaN(reg.fd[fs>>1]) || isNaN(reg.fd[ft>>1])) { + fc = FP_U; + break; + } + if(reg.fd[fs>>1] == reg.fd[ft>>1]) { + fc = FP_E; + break; + } + if(reg.fd[fs>>1] < reg.fd[ft>>1]) { + fc = FP_L; + break; + } + if(reg.fd[fs>>1] > reg.fd[ft>>1]) { + fc = FP_G; + break; + } + print("vi: bad in fcmp"); + break; + case 4: + fmt = 'w'; + if(reg.di[fs] == reg.di[ft]) { + fc = FP_E; + break; + } + if(reg.di[fs] < reg.di[ft]) { + fc = FP_L; + break; + } + if(reg.di[fs] > reg.di[ft]) { + fc = FP_G; + break; + } + break; + } + + reg.fpsr &= ~FP_CBIT; + switch(ir&0xf) { + case 0: + if(trace) + itrace("c.f.%c\tf%d,f%d", fmt, fs, ft); + break; + case 1: + if(trace) + itrace("c.un.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_U) + reg.fpsr |= FP_CBIT; + break; + case 2: + if(trace) + itrace("c.eq.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E) + reg.fpsr |= FP_CBIT; + break; + case 3: + if(trace) + itrace("c.ueq.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E || fc == FP_U) + reg.fpsr |= FP_CBIT; + break; + case 4: + if(trace) + itrace("c.lt.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_L) + reg.fpsr |= FP_CBIT; + break; + case 5: + if(trace) + itrace("c.ult.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_L || fc == FP_U) + reg.fpsr |= FP_CBIT; + break; + case 6: + if(trace) + itrace("c.le.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E || fc == FP_L) + reg.fpsr |= FP_CBIT; + break; + case 7: + if(trace) + itrace("c.ule.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E || fc == FP_L || fc == FP_U) + reg.fpsr |= FP_CBIT; + break; + case 8: + if(trace) + itrace("c.sf.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_U) + inval(ir); + break; + case 9: + if(trace) + itrace("c.ngle.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_U) { + reg.fpsr |= FP_CBIT; + inval(ir); + } + break; + case 10: + if(trace) + itrace("c.seq.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E) + reg.fpsr |= FP_CBIT; + if(fc == FP_U) + inval(ir); + break; + case 11: + if(trace) + itrace("c.ngl.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E || fc == FP_U) + reg.fpsr |= FP_CBIT; + if(fc == FP_U) + inval(ir); + break; + case 12: + if(trace) + itrace("c.lt.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_L) + reg.fpsr |= FP_CBIT; + if(fc == FP_U) + inval(ir); + break; + case 13: + if(trace) + itrace("c.nge.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_L || fc == FP_U) + reg.fpsr |= FP_CBIT; + if(fc == FP_U) + inval(ir); + break; + case 14: + if(trace) + itrace("c.le.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E || fc == FP_L) + reg.fpsr |= FP_CBIT; + if(fc == FP_U) + inval(ir); + break; + case 15: + if(trace) + itrace("c.ngt.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E || fc == FP_L || fc == FP_U) + reg.fpsr |= FP_CBIT; + if(fc == FP_U) + inval(ir); + break; + } + USED(fmt); +} diff --git a/sys/src/cmd/vi/icache.c b/sys/src/cmd/vi/icache.c new file mode 100755 index 000000000..71e448860 --- /dev/null +++ b/sys/src/cmd/vi/icache.c @@ -0,0 +1,18 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "mips.h" + +void +icacheinit(void) +{ +} + +void +updateicache(ulong addr) +{ + USED(addr); +} + diff --git a/sys/src/cmd/vi/mem.c b/sys/src/cmd/vi/mem.c new file mode 100755 index 000000000..9ab40da5d --- /dev/null +++ b/sys/src/cmd/vi/mem.c @@ -0,0 +1,285 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "mips.h" + +extern ulong textbase; + +ulong +ifetch(ulong addr) +{ + uchar *va; + + if(addr&3) { + Bprint(bioout, "Address error (I-fetch) vaddr %.8lux\n", addr); + longjmp(errjmp, 0); + } + + if(icache.on) + updateicache(addr); + + iprof[(addr-textbase)/PROFGRAN]++; + + va = vaddr(addr); + va += addr&(BY2PG-1); + + return va[0]<<24 | va[1]<<16 | va[2]<<8 | va[3]; +} + +ulong +getmem_4(ulong addr) +{ + ulong val; + int i; + + val = 0; + for(i = 0; i < 4; i++) + val = val<<8 | getmem_b(addr++); + return val; +} + +ulong +getmem_2(ulong addr) +{ + ulong val; + + val = getmem_b(addr); + val = val<<8 | getmem_b(addr+1); + + return val; +} + +ulong +getmem_w(ulong addr) +{ + uchar *va; + + if(addr&3) { + Bprint(bioout, "Address error (Load) vaddr %.8lux\n", addr); + longjmp(errjmp, 0); + } + if(membpt) + brkchk(addr, Read); + + va = vaddr(addr); + va += addr&(BY2PG-1); + + return va[0]<<24 | va[1]<<16 | va[2]<<8 | va[3];; +} + +ushort +getmem_h(ulong addr) +{ + uchar *va; + + if(addr&1) { + Bprint(bioout, "Address error (Load) vaddr %.8lux\n", addr); + longjmp(errjmp, 0); + } + if(membpt) + brkchk(addr, Read); + + va = vaddr(addr); + va += addr&(BY2PG-1); + + return va[0]<<8 | va[1]; +} + +uchar +getmem_b(ulong addr) +{ + uchar *va; + + if(membpt) + brkchk(addr, Read); + + va = vaddr(addr); + va += addr&(BY2PG-1); + return va[0]; +} + +void +putmem_w(ulong addr, ulong data) +{ + uchar *va; + + if(addr&3) { + Bprint(bioout, "Address error (Store) vaddr %.8lux\n", addr); + longjmp(errjmp, 0); + } + + va = vaddr(addr); + va += addr&(BY2PG-1); + + va[0] = data>>24; + va[1] = data>>16; + va[2] = data>>8; + va[3] = data; + if(membpt) + brkchk(addr, Write); +} +void +putmem_b(ulong addr, uchar data) +{ + uchar *va; + + va = vaddr(addr); + va += addr&(BY2PG-1); + va[0] = data; + if(membpt) + brkchk(addr, Write); +} + +void +putmem_h(ulong addr, short data) +{ + uchar *va; + + if(addr&1) { + Bprint(bioout, "Address error (Store) vaddr %.8lux\n", addr); + longjmp(errjmp, 0); + } + + va = vaddr(addr); + va += addr&(BY2PG-1); + va[0] = data>>8; + va[1] = data; + if(membpt) + brkchk(addr, Write); +} + +char * +memio(char *mb, ulong mem, int size, int dir) +{ + int i; + char *buf, c; + + if(mb == 0) + mb = emalloc(size); + + buf = mb; + switch(dir) { + default: + fatal(0, "memio"); + case MemRead: + while(size--) + *mb++ = getmem_b(mem++); + break; + case MemReadstring: + for(;;) { + if(size-- == 0) { + Bprint(bioout, "memio: user/kernel copy too long for mipsim\n"); + longjmp(errjmp, 0); + } + c = getmem_b(mem++); + *mb++ = c; + if(c == '\0') + break; + } + break; + case MemWrite: + for(i = 0; i < size; i++) + putmem_b(mem++, *mb++); + break; + } + return buf; +} + +void +dotlb(ulong vaddr) +{ + ulong *l, *e; + + vaddr &= ~(BY2PG-1); + + e = &tlb.tlbent[tlb.tlbsize]; + for(l = tlb.tlbent; l < e; l++) + if(*l == vaddr) { + tlb.hit++; + return; + } + + tlb.miss++; + tlb.tlbent[lnrand(tlb.tlbsize)] = vaddr; +} + +void* +vaddr1(ulong addr) +{ + Segment *s, *es; + int off, foff, l, n; + uchar **p, *a; + + if(tlb.on) + dotlb(addr); + + es = &memory.seg[Nseg]; + for(s = memory.seg; s < es; s++) { + if(addr >= s->base && addr < s->end) { + s->refs++; + off = (addr-s->base)/BY2PG; + p = &s->table[off]; + if(*p) + return *p; + s->rss++; + switch(s->type) { + default: + fatal(0, "vaddr"); + case Text: + *p = emalloc(BY2PG); + if(seek(text, s->fileoff+(off*BY2PG), 0) < 0) + fatal(1, "vaddr text seek"); + if(read(text, *p, BY2PG) < 0) + fatal(1, "vaddr text read"); + return *p; + case Data: + *p = emalloc(BY2PG); + foff = s->fileoff+(off*BY2PG); + if(seek(text, foff, 0) < 0) + fatal(1, "vaddr text seek"); + n = read(text, *p, BY2PG); + if(n < 0) + fatal(1, "vaddr text read"); + if(foff + n > s->fileend) { + l = BY2PG - (s->fileend-foff); + a = *p+(s->fileend-foff); + memset(a, 0, l); + } + return *p; + case Bss: + case Stack: + *p = emalloc(BY2PG); + return *p; + } + } + } + return 0; +} + +void* +vaddr(ulong addr) +{ + void *v; + + v = vaddr1(addr); + if(v == 0) { + Bprint(bioout, "User TLB miss vaddr 0x%.8lux\n", addr); + longjmp(errjmp, 0); + } + return v; +} + +int +badvaddr(ulong addr, int n) +{ + void *v; + + if(addr & (n-1)) + return 1; + v = vaddr1(addr); + if(v == 0) + return 1; + return 0; +} diff --git a/sys/src/cmd/vi/mips.h b/sys/src/cmd/vi/mips.h new file mode 100755 index 000000000..a389f2dcf --- /dev/null +++ b/sys/src/cmd/vi/mips.h @@ -0,0 +1,257 @@ +/* + * mipsim.h + */ +#include "/mips/include/ureg.h" +#define USERADDR 0xC0000000 +#define UREGADDR (USERADDR+BY2PG-4-0xA0) +#define USER_REG(x) (UREGADDR+(ulong)(x)) +#define REGOFF(x) (USER_REG(&((struct Ureg *) 0)->x)) + +typedef struct Registers Registers; +typedef struct Segment Segment; +typedef struct Memory Memory; +typedef struct Mul Mul; +typedef struct Mulu Mulu; +typedef struct Inst Inst; +typedef struct Icache Icache; +typedef struct Tlb Tlb; +typedef struct Breakpoint Breakpoint; + +enum +{ + Instruction = 1, + Read = 2, + Write = 4, + Access = 2|4, + Equal = 4|8, +}; + +struct Breakpoint +{ + int type; /* Instruction/Read/Access/Write/Equal */ + ulong addr; /* Place at address */ + int count; /* To execute count times or value */ + int done; /* How many times passed through */ + Breakpoint *next; /* Link to next one */ +}; + +enum +{ + Iload, + Istore, + Iarith, + Ibranch, + Ireg, + Isyscall, + Ifloat, +}; + +enum +{ + Nmaxtlb = 64, +}; + +struct Tlb +{ + int on; /* Being updated */ + int tlbsize; /* Number of entries */ + ulong tlbent[Nmaxtlb]; /* Virtual address tags */ + int hit; /* Number of successful tag matches */ + int miss; /* Number of failed tag matches */ +}; + +struct Icache +{ + int on; /* Turned on */ + int linesize; /* Line size in bytes */ + int stall; /* Cache stalls */ + int *lines; /* Tag array */ + int* (*hash)(ulong); /* Hash function */ + char *hashtext; /* What the function looks like */ +}; + +struct Inst +{ + void (*func)(ulong); + char *name; + int type; + int count; + int taken; + int useddelay; +}; + +struct Registers +{ + ulong pc; + ulong ir; + Inst *ip; + long r[32]; + ulong mhi; + ulong mlo; + + ulong fpsr; + union { + double fd[16]; + float fl[32]; + ulong di[32]; + }; + char ft[32]; +}; + +enum +{ + FPd = 0, + FPs, + FPmemory, +}; +#define dreg(r) ((r)>>1) + +struct Mulu +{ + ulong lo; + ulong hi; +}; + +struct Mul +{ + long lo; + long hi; +}; + +enum +{ + MemRead, + MemReadstring, + MemWrite, +}; + +enum +{ + Stack, + Text, + Data, + Bss, + Nseg, +}; + +struct Segment +{ + short type; + ulong base; + ulong end; + ulong fileoff; + ulong fileend; + int rss; + int refs; + uchar **table; +}; + +struct Memory +{ + Segment seg[Nseg]; +}; + +void fatal(int, char*, ...); +void run(void); +void undef(ulong); +void dumpreg(void); +void dumpfreg(void); +void dumpdreg(void); +void* emalloc(ulong); +void* erealloc(void*, ulong, ulong); +void* vaddr(ulong); +int badvaddr(ulong, int); +void itrace(char *, ...); +void segsum(void); +void Ssyscall(ulong); +char* memio(char*, ulong, int, int); +ulong ifetch(ulong); +ulong getmem_w(ulong); +ushort getmem_h(ulong); +void putmem_w(ulong, ulong); +uchar getmem_b(ulong); +void putmem_b(ulong, uchar); +ulong getmem_4(ulong); +ulong getmem_2(ulong); +void putmem_h(ulong, short); +Mul mul(long, long); +Mulu mulu(ulong, ulong); +void isum(void); +void initicache(void); +void updateicache(ulong addr); +void tlbsum(void); +long lnrand(long); +void randseed(long, long); +void cmd(void); +void brkchk(ulong, int); +void delbpt(char*); +void breakpoint(char*, char*); +char* nextc(char*); +ulong expr(char*); +void initmap(void); +void inithdr(int); +void initstk(int, char**); +void reset(void); +void dobplist(void); +int _mipscoinst(Map*, uvlong, char*, int); +void procinit(int); +void printsource(long); +void printparams(Symbol *, ulong); +void printlocals(Symbol *, ulong); +void stktrace(int); +void iprofile(void); + +/* Globals */ +Extern Registers reg; +Extern Memory memory; +Extern int text; +Extern int trace; +Extern int sysdbg; +Extern int calltree; +Extern Inst itab[]; +Extern Inst ispec[]; +Extern Icache icache; +Extern Tlb tlb; +Extern int count; +Extern jmp_buf errjmp; +Extern Breakpoint *bplist; +Extern int atbpt; +Extern int membpt; +Extern int cmdcount; +Extern int nopcount; +Extern ulong dot; +extern char *file; +Extern Biobuf *bioout; +Extern Biobuf *bin; +Extern ulong *iprof; +extern int datasize; +Extern Map *symmap; +Extern int rtrace; + +/* Plan9 Kernel constants */ +#define BY2PG 4096 +#define BY2WD 4 +#define UTZERO 0x1000 +#define STACKTOP 0x80000000 +#define STACKSIZE 0x10000 + +#define PROFGRAN 4 +/* Opcode decoders */ +#define Getrsrt(s,t,i) s = (i>>21)&0x1f; t = (i>>16)&0x1f; +#define Getrbrt(b,t,i) b = (i>>21)&0x1f; t = (i>>16)&0x1f; +#define Get3(s, t, d, i) s = (i>>21)&0x1f; t = (i>>16)&0x1f; d = (i>>11)&0x1f; +#define Getf3(s, t, d, i) s = (i>>11)&0x1f; t = (i>>16)&0x1f; d = (i>>6)&0x1f; +#define Getf2(s, d, i) s = (i>>11)&0x1f; d = (i>>6)&0x1f; +#define SpecialGetrtrd(t, d, i) t = (i>>16)&0x1f; d = (i>>11)&0x1f; + +#define INOPINST "nor" +#define INOP 0x00000027 /* Instruction used as nop */ +#define SIGNBIT 0x80000000 +#define Iexec(ir) {Inst *i; i = &itab[(ir)>>26]; reg.ip = i; i->count++; (*i->func)(ir); } +#define Statbra() reg.ip->taken++; if(reg.ir != INOP) reg.ip->useddelay++; + +#define FP_U 3 +#define FP_L 1 +#define FP_G 2 +#define FP_E 0 +#define FP_CBIT (1<<23) diff --git a/sys/src/cmd/vi/mkfile b/sys/src/cmd/vi/mkfile new file mode 100755 index 000000000..c1eb2b896 --- /dev/null +++ b/sys/src/cmd/vi/mkfile @@ -0,0 +1,28 @@ +</$objtype/mkfile + +TARG=vi +OFILES=vi.$O\ + run.$O\ + special.$O\ + mem.$O\ + syscall.$O\ + stats.$O\ + icache.$O\ + symbols.$O\ + cmd.$O\ + bpt.$O\ + float.$O\ + +HFILES=mips.h\ + +BIN=/$objtype/bin + +UPDATE=\ + mkfile\ + $HFILES\ + ${OFILES:%.$O=%.c}\ + +</sys/src/cmd/mkone + +acid: + $CC -a run.c > acid.def diff --git a/sys/src/cmd/vi/run.c b/sys/src/cmd/vi/run.c new file mode 100755 index 000000000..bf3883679 --- /dev/null +++ b/sys/src/cmd/vi/run.c @@ -0,0 +1,869 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "mips.h" + +void Iaddi(ulong); +void Isw(ulong); +void Ilui(ulong); +void Iori(ulong); +void Ixori(ulong); +void Ilw(ulong); +void Ijal(ulong); +void Ispecial(ulong); +void Ibeq(ulong); +void Ibeql(ulong); +void Iaddiu(ulong); +void Ilb(ulong); +void Iandi(ulong); +void Ij(ulong); +void Ibne(ulong); +void Ibnel(ulong); +void Isb(ulong); +void Islti(ulong); +void Ibcond(ulong); +void Ibgtz(ulong); +void Ibgtzl(ulong); +void Ilbu(ulong); +void Ilhu(ulong); +void Ish(ulong); +void Ilh(ulong); +void Iblez(ulong); +void Iblezl(ulong); +void Isltiu(ulong); +void Iswc1(ulong); +void Ilwc1(ulong); +void Icop1(ulong); +void Ilwl(ulong); +void Ilwr(ulong); +void Ill(ulong); +void Isc(ulong); + +Inst itab[] = { + { Ispecial, 0 }, + { Ibcond, "bcond", Ibranch }, + { Ij, "j", Ibranch }, + { Ijal, "jal", Ibranch }, + { Ibeq, "beq", Ibranch }, + { Ibne, "bne", Ibranch }, + { Iblez, "blez", Ibranch }, + { Ibgtz, "bgtz", Ibranch }, + { Iaddi, "addi", Iarith }, /* 8 */ + { Iaddiu, "addiu", Iarith }, + { Islti, "slti", Iarith }, + { Isltiu, "sltiu", Iarith }, + { Iandi, "andi", Iarith }, + { Iori, "ori", Iarith }, + { Ixori, "xori", Iarith }, + { Ilui, "lui", Iload }, /* 15 */ + { undef, "" }, + { Icop1, "cop1", Ifloat }, + { undef, "" }, + { undef, "" }, + { Ibeql, "beql" }, + { Ibnel, "bnel" }, + { Iblezl, "blezl" }, + { Ibgtzl, "bgtzl" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { Ilb, "lb", Iload }, + { Ilh, "lh", Iload }, + { Ilwl, "lwl", Iload }, + { Ilw, "lw", Iload }, + { Ilbu, "lbu", Iload }, + { Ilhu, "lhu", Iload }, + { Ilwr, "lwr", Iload }, + { undef, "" }, + { Isb, "sb", Istore }, + { Ish, "sh", Istore }, + { undef, "" }, + { Isw, "sw", Istore }, /* 43 */ + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { Ill, "ll", Iload}, + { Ilwc1, "lwc1", Ifloat }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { Isc, "sc", Istore }, + { Iswc1, "swc1", Ifloat }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { 0 } +}; + +void +dortrace(void) +{ + int i; + + for(i = 0; i < 32; i++) + if(rtrace & (1<<i)) + Bprint(bioout, "R%.2d %.8lux\n", i, reg.r[i]); +} + +void +run(void) +{ + do { + reg.r[0] = 0; + reg.ir = ifetch(reg.pc); + Iexec(reg.ir); + reg.pc += 4; + if(bplist) + brkchk(reg.pc, Instruction); + if(rtrace) + dortrace(); +Bflush(bioout); + }while(--count); +} + +void +undef(ulong inst) +{ + +/* + if((reg.ir>>26) == 0) + Bprint(bioout, "special=%d,%d table=%d\n", + (reg.ir>>3)&0x7, reg.ir&0x7, reg.ir&0x3f); + else + Bprint(bioout, "code=%d,%d table=%d\n", + reg.ir>>29, (reg.ir>>26)&0x7, reg.ir>>26); +*/ + + Bprint(bioout, "Undefined Instruction Trap IR %.8lux\n", inst); + longjmp(errjmp, 0); +} + +void +Iaddi(ulong inst) +{ + int rs, rt; + int imm; + + Getrsrt(rs, rt, inst); + imm = (short)(inst&0xffff); + + if(trace) + itrace("addi\tr%d,r%d,#0x%x", rt, rs, imm); + + reg.r[rt] = reg.r[rs] + imm; +} + +void +Iandi(ulong inst) +{ + int rs, rt; + int imm; + + Getrsrt(rs, rt, inst); + imm = inst&0xffff; + + if(trace) + itrace("andi\tr%d,r%d,#0x%x", rt, rs, imm); + + reg.r[rt] = reg.r[rs] & imm; +} + +void +Isw(ulong inst) +{ + int rt, rb; + int off; + ulong v; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + v = reg.r[rt]; + if(trace) + itrace("sw\tr%d,0x%x(r%d) %lux=%lux", + rt, off, rb, reg.r[rb]+off, v); + + putmem_w(reg.r[rb]+off, v); +} + +void +Isb(ulong inst) +{ + int rt, rb; + int off; + uchar value; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + value = reg.r[rt]; + if(trace) + itrace("sb\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, reg.r[rb]+off, value); + + putmem_b(reg.r[rb]+off, value); +} + +void +Ish(ulong inst) +{ + int rt, rb; + int off; + ushort value; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + value = reg.r[rt]; + if(trace) + itrace("sh\tr%d,0x%x(r%d) %lux=%lux", + rt, off, rb, reg.r[rb]+off, value&0xffff); + + putmem_h(reg.r[rb]+off, value); +} + +void +Ilui(ulong inst) +{ + int rs, rt; + int imm; + + Getrsrt(rs, rt, inst); + USED(rs); + imm = inst<<16; + + if(trace) + itrace("lui\tr%d,#0x%x", rt, imm); + + reg.r[rt] = imm; +} + +void +Iori(ulong inst) +{ + int rs, rt; + int imm; + + Getrsrt(rs, rt, inst); + imm = inst&0xffff; + + if(trace) + itrace("ori\tr%d,r%d,#0x%x", rt, rs, imm); + + reg.r[rt] = reg.r[rs] | imm; +} + +void +Ixori(ulong inst) +{ + int rs, rt; + int imm; + + Getrsrt(rs, rt, inst); + imm = inst&0xffff; + + if(trace) + itrace("xori\tr%d,r%d,#0x%x", rt, rs, imm); + + reg.r[rt] = reg.r[rs] ^ imm; +} + +void +Ilw(ulong inst) +{ + int rt, rb; + int off; + ulong v, va; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + va = reg.r[rb]+off; + + if(trace) { + v = 0; + if(!badvaddr(va, 4)) + v = getmem_w(va); + itrace("lw\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); + } + + reg.r[rt] = getmem_w(va); +} + +void +Ilwl(ulong inst) +{ + int rt, rb; + int off; + ulong v, va; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + va = reg.r[rb]+off; + + if(trace) { + v = 0; + if(!badvaddr(va, 4)) + v = getmem_w(va & ~3) << ((va & 3) << 3); + itrace("lwl\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); + } + + v = getmem_w(va & ~3); + switch(va & 3) { + case 0: + reg.r[rt] = v; + break; + case 1: + reg.r[rt] = (v<<8) | (reg.r[rt] & 0xff); + break; + case 2: + reg.r[rt] = (v<<16) | (reg.r[rt] & 0xffff); + break; + case 3: + reg.r[rt] = (v<<24) | (reg.r[rt] & 0xffffff); + break; + } +} + +void +Ilwr(ulong inst) +{ + int rt, rb; + int off; + ulong v, va; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + va = reg.r[rb]+off; + + if(trace) { + v = 0; + if(!badvaddr(va, 4)) + v = getmem_w(va & ~3) << ((va & 3) << 3); + itrace("lwr\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); + } + + v = getmem_w(va & ~3); + switch(va & 3) { + case 0: + break; + case 1: + reg.r[rt] = (v>>24) | (reg.r[rt] & 0xffffff00); + break; + case 2: + reg.r[rt] = (v>>16) | (reg.r[rt] & 0xffff0000); + break; + case 3: + reg.r[rt] = (v>>8) | (reg.r[rt] & 0xff000000); + break; + } +} + +void +Ilh(ulong inst) +{ + int rt, rb; + int off; + ulong v, va; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + va = reg.r[rb]+off; + + if(trace) { + v = 0; + if(!badvaddr(va, 2)) + v = (short)getmem_h(va); + itrace("lw\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); + } + + reg.r[rt] = (short)getmem_h(va); +} + +void +Ilhu(ulong inst) +{ + int rt, rb; + int off; + ulong v, va; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + va = reg.r[rb]+off; + + if(trace) { + v = 0; + if(!badvaddr(va, 2)) + v = getmem_h(va) & 0xffff; + itrace("lhu\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); + } + + reg.r[rt] = getmem_h(va) & 0xffff; +} + +void +Ilb(ulong inst) +{ + int rt, rb; + int off; + ulong v, va; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + va = reg.r[rb]+off; + + if(trace) { + v = 0; + if(!badvaddr(va, 1)) + v = (schar)getmem_b(va); + itrace("lb\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); + } + + reg.r[rt] = (schar)getmem_b(va); +} + +void +Ilbu(ulong inst) +{ + int rt, rb; + int off; + ulong v, va; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + va = reg.r[rb]+off; + + if(trace) { + v = 0; + if(!badvaddr(va, 1)) + v = getmem_b(va) & 0xff; + itrace("lbu\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); + } + + reg.r[rt] = getmem_b(va) & 0xff; +} + +void +Ijal(ulong inst) +{ + ulong npc; + Symbol s; + + npc = (reg.pc&0xF0000000)|((inst&0x3FFFFFF)<<2); + if(trace) + itrace("jal\t0x%lux", npc); + + reg.r[31] = reg.pc+8; + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + + if(calltree) { + findsym(npc, CTEXT, &s); + Bprint(bioout, "%8lux %s(", reg.pc, s.name); + printparams(&s, reg.r[29]); + Bprint(bioout, "from "); + printsource(reg.pc); + Bputc(bioout, '\n'); + } + + reg.pc = npc-4; +} + +void +Ij(ulong inst) +{ + ulong npc; + + npc = (reg.pc&0xF0000000)|((inst&0x3FFFFFF)<<2); + if(trace) + itrace("j\t0x%lux", npc); + + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + reg.pc = npc-4; +} + +void +Ibeq(ulong inst) +{ + int rt, rs; + int off; + ulong npc; + + Getrsrt(rs, rt, inst); + off = (short)(inst&0xffff); + + npc = reg.pc + (off<<2) + 4; + if(trace) + itrace("beq\tr%d,r%d,0x%lux", rs, rt, npc); + + if(reg.r[rs] == reg.r[rt]) { + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + reg.pc = npc-4; + } +} + +void +Ibeql(ulong inst) +{ + int rt, rs; + int off; + ulong npc; + + Getrsrt(rs, rt, inst); + off = (short)(inst&0xffff); + + npc = reg.pc + (off<<2) + 4; + if(trace) + itrace("beq\tr%d,r%d,0x%lux", rs, rt, npc); + + if(reg.r[rs] == reg.r[rt]) { + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + reg.pc = npc-4; + } else + reg.pc += 4; +} + +void +Ibgtz(ulong inst) +{ + int rs; + int off; + ulong npc, r; + + rs = (inst>>21)&0x1f; + off = (short)(inst&0xffff); + + npc = reg.pc + (off<<2) + 4; + if(trace) + itrace("bgtz\tr%d,0x%lux", rs, npc); + + r = reg.r[rs]; + if(!(r&SIGNBIT) && r != 0) { + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Iexec(reg.ir); + reg.pc = npc-4; + } +} + +void +Ibgtzl(ulong inst) +{ + int rs; + int off; + ulong npc, r; + + rs = (inst>>21)&0x1f; + off = (short)(inst&0xffff); + + npc = reg.pc + (off<<2) + 4; + if(trace) + itrace("bgtz\tr%d,0x%lux", rs, npc); + + r = reg.r[rs]; + if(!(r&SIGNBIT) && r != 0) { + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Iexec(reg.ir); + reg.pc = npc-4; + } else + reg.pc += 4; +} + +void +Iblez(ulong inst) +{ + int rs; + int off; + ulong npc, r; + + rs = (inst>>21)&0x1f; + off = (short)(inst&0xffff); + + npc = reg.pc + (off<<2) + 4; + if(trace) + itrace("blez\tr%d,0x%lux", rs, npc); + + r = reg.r[rs]; + if((r&SIGNBIT) || r == 0) { + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + reg.pc = npc-4; + } +} + +void +Iblezl(ulong inst) +{ + int rs; + int off; + ulong npc, r; + + rs = (inst>>21)&0x1f; + off = (short)(inst&0xffff); + + npc = reg.pc + (off<<2) + 4; + if(trace) + itrace("blez\tr%d,0x%lux", rs, npc); + + r = reg.r[rs]; + if((r&SIGNBIT) || r == 0) { + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + reg.pc = npc-4; + } else + reg.pc += 4; +} + +void +Ibne(ulong inst) +{ + int rt, rs; + int off; + ulong npc; + + Getrsrt(rs, rt, inst); + off = (short)(inst&0xffff); + + npc = reg.pc + (off<<2) + 4; + if(trace) + itrace("bne\tr%d,r%d,0x%lux", rs, rt, npc); + + if(reg.r[rs] != reg.r[rt]) { + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + reg.pc = npc-4; + } +} + +void +Ibnel(ulong inst) +{ + int rt, rs; + int off; + ulong npc; + + Getrsrt(rs, rt, inst); + off = (short)(inst&0xffff); + + npc = reg.pc + (off<<2) + 4; + if(trace) + itrace("bne\tr%d,r%d,0x%lux", rs, rt, npc); + + if(reg.r[rs] != reg.r[rt]) { + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + reg.pc = npc-4; + } else + reg.pc += 4; +} + +void +Iaddiu(ulong inst) +{ + int rs, rt; + int imm; + + Getrsrt(rs, rt, inst); + imm = (short)(inst&0xffff); + + if(trace) + itrace("addiu\tr%d,r%d,#0x%x", rt, rs, imm); + + reg.r[rt] = reg.r[rs]+imm; +} + +void +Islti(ulong inst) +{ + int rs, rt; + int imm; + + Getrsrt(rs, rt, inst); + imm = (short)(inst&0xffff); + + if(trace) + itrace("slti\tr%d,r%d,#0x%x", rt, rs, imm); + + reg.r[rt] = reg.r[rs] < imm ? 1 : 0; +} + +void +Isltiu(ulong inst) +{ + int rs, rt; + int imm; + + Getrsrt(rs, rt, inst); + imm = (short)(inst&0xffff); + + if(trace) + itrace("sltiu\tr%d,r%d,#0x%x", rt, rs, imm); + + reg.r[rt] = (ulong)reg.r[rs] < (ulong)imm ? 1 : 0; +} + +/* ll and sc are implemented as lw and sw, since we simulate a uniprocessor */ + +void +Ill(ulong inst) +{ + int rt, rb; + int off; + ulong v, va; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + va = reg.r[rb]+off; + + if(trace) { + v = 0; + if(!badvaddr(va, 4)) + v = getmem_w(va); + itrace("ll\tr%d,0x%x(r%d) %lux=%lux", rt, off, rb, va, v); + } + + reg.r[rt] = getmem_w(va); +} + +void +Isc(ulong inst) +{ + int rt, rb; + int off; + ulong v; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + v = reg.r[rt]; + if(trace) + itrace("sc\tr%d,0x%x(r%d) %lux=%lux", + rt, off, rb, reg.r[rb]+off, v); + + putmem_w(reg.r[rb]+off, v); +} + +enum +{ + Bltz = 0, + Bgez = 1, + Bltzal = 0x10, + Bgezal = 0x11, + Bltzl = 2, + Bgezl = 3, + Bltzall = 0x12, + Bgezall = 0x13, +}; + +static char *sbcond[] = +{ + [Bltz] "ltz", + [Bgez] "gez", + [Bltzal] "ltzal", + [Bgezal] "gezal", + [Bltzl] "ltzl", + [Bgezl] "gezl", + [Bltzall] "ltzall", + [Bgezall] "gezall", +}; + +void +Ibcond(ulong inst) +{ + int rs, bran; + int off, doit, likely; + ulong npc; + + rs = (inst>>21)&0x1f; + bran = (inst>>16)&0x1f; + off = (short)(inst&0xffff); + doit = 0; + likely = 0; + + npc = reg.pc + (off<<2) + 4; + switch(bran) { + default: + Bprint(bioout, "bcond=%d\n", bran); + undef(inst); + case Bltzl: + likely = 1; + case Bltz: + if(reg.r[rs]&SIGNBIT) + doit = 1; + break; + case Bgezl: + likely = 1; + case Bgez: + if(!(reg.r[rs]&SIGNBIT)) + doit = 1; + break; + case Bltzall: + likely = 1; + case Bltzal: + reg.r[31] = reg.pc+8; + if(reg.r[rs]&SIGNBIT) + doit = 1; + break; + case Bgezall: + likely = 1; + case Bgezal: + reg.r[31] = reg.pc+8; + if(!(reg.r[rs]&SIGNBIT)) + doit = 1; + break; + } + + if(trace) + itrace("b%s\tr%d,0x%lux", sbcond[bran], rs, npc); + + if(doit) { + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + reg.pc = npc-4; + } else + if(likely) + reg.pc += 4; + +} diff --git a/sys/src/cmd/vi/special.c b/sys/src/cmd/vi/special.c new file mode 100755 index 000000000..99032f1f4 --- /dev/null +++ b/sys/src/cmd/vi/special.c @@ -0,0 +1,444 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "mips.h" + +void Snor(ulong); +void Ssll(ulong); +void Ssra(ulong); +void Sslt(ulong); +void Ssltu(ulong); +void Sand(ulong); +void Saddu(ulong); +void Sadd(ulong); +void Sjr(ulong); +void Sor(ulong); +void Ssubu(ulong); +void Sjalr(ulong); +void Sdivu(ulong); +void Smfhi(ulong); +void Smflo(ulong); +void Sxor(ulong); +void Smult(ulong); +void Smultu(ulong); +void Sdiv(ulong); +void Ssrl(ulong); +void Ssllv(ulong); +void Ssrlv(ulong); +void Ssrav(ulong); + +Inst ispec[] = +{ + { Ssll, "sll", Iarith }, + { undef, "" }, + { Ssrl, "srl", Iarith }, + { Ssra, "sra", Iarith }, + { Ssllv, "sllv", Iarith }, + { undef, "" }, + { Ssrlv, "srlv", Iarith }, + { Ssrav, "srav", Iarith }, + { Sjr, "jr", Ibranch }, + { Sjalr, "jalr", Ibranch }, + { undef, "" }, + { undef, "" }, + { Ssyscall, "sysc", Isyscall }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { Smfhi, "mfhi", Ireg }, + { undef, "" }, + { Smflo, "mflo", Ireg }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { Smult, "mult", Iarith }, + { Smultu, "multu" }, + { Sdiv, "div", Iarith }, + { Sdivu, "divu", Iarith }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { Sadd, "add", Iarith }, + { Saddu, "addu", Iarith }, + { undef, "" }, + { Ssubu, "subu", Iarith }, + { Sand, "and", Iarith }, + { Sor, "or", Iarith }, + { Sxor, "xor", Iarith }, + { Snor, "nor", Iarith }, + { undef, "" }, + { undef, "" }, + { Sslt, "slt", Iarith }, + { Ssltu, "sltu", Iarith }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { 0 } +}; + +void +Ispecial(ulong inst) +{ + Inst *i; + + i = &ispec[inst&0x3f]; + reg.ip = i; + i->count++; + (*i->func)(inst); +} + +void +Snor(ulong inst) +{ + int rs, rt, rd; + + Get3(rs, rt, rd, inst); + if(trace) + itrace("nor\tr%d,r%d,r%d", rd, rs, rt); + + if(inst == INOP) + nopcount++; + else + reg.r[rd] = ~(reg.r[rt]|reg.r[rs]); +} + +void +Ssll(ulong inst) +{ + int rd, rt, shamt; + + SpecialGetrtrd(rt, rd, inst); + shamt = (inst>>6)&0x1f; + if(trace) + itrace("sll\tr%d,r%d,%d", rd, rt, shamt); + + reg.r[rd] = reg.r[rt]<<shamt; +} + +void +Ssllv(ulong inst) +{ + int rd, rt, rs; + + Get3(rs, rt, rd, inst); + if(trace) + itrace("sllv\tr%d,r%d,r%d", rd, rt, rs); + + reg.r[rd] = reg.r[rt]<<(reg.r[rs]&0x1f); +} + +void +Ssrlv(ulong inst) +{ + int rd, rt, rs; + + Get3(rs, rt, rd, inst); + if(trace) + itrace("srlv\tr%d,r%d,r%d", rd, rt, rs); + + reg.r[rd] = (ulong)reg.r[rt] >> (reg.r[rs]&0x1f); +} + +void +Ssrav(ulong inst) +{ + int rd, rt, rs, shamt; + + Get3(rs, rt, rd, inst); + if(trace) + itrace("srav\tr%d,r%d,r%d", rd, rt, rs); + + shamt = reg.r[rs]&0x1f; + if(shamt != 0 && (reg.r[rt] & SIGNBIT)) + reg.r[rd] = reg.r[rt]>>shamt | ~((1<<(32-shamt))-1); + else + reg.r[rd] = reg.r[rt]>>shamt; +} + +void +Ssrl(ulong inst) +{ + int rd, rt, shamt; + + SpecialGetrtrd(rt, rd, inst); + shamt = (inst>>6)&0x1f; + if(trace) + itrace("srl\tr%d,r%d,%d", rd, rt, shamt); + + reg.r[rd] = (ulong)reg.r[rt] >> shamt; +} + +void +Ssra(ulong inst) +{ + int rd, rt, shamt; + + SpecialGetrtrd(rt, rd, inst); + shamt = (inst>>6)&0x1f; + if(trace) + itrace("sra\tr%d,r%d,%d", rd, rt, shamt); + + if(shamt != 0 && (reg.r[rt] & SIGNBIT)) + reg.r[rd] = reg.r[rt]>>shamt | ~((1<<(32-shamt))-1); + else + reg.r[rd] = reg.r[rt]>>shamt; +} + +void +Sslt(ulong inst) +{ + int rs, rt, rd; + + Get3(rs, rt, rd, inst); + if(trace) + itrace("slt\tr%d,r%d,r%d", rd, rs, rt); + + reg.r[rd] = reg.r[rs] < reg.r[rt] ? 1 : 0; +} + +void +Ssltu(ulong inst) +{ + int rs, rt, rd; + + Get3(rs, rt, rd, inst); + if(trace) + itrace("sltu\tr%d,r%d,r%d", rd, rs, rt); + + reg.r[rd] = (unsigned)reg.r[rs] < (unsigned)reg.r[rt] ? 1 : 0; +} + +void +Sand(ulong inst) +{ + int rs, rt, rd; + + Get3(rs, rt, rd, inst); + if(trace) + itrace("and\tr%d,r%d,r%d", rd, rs, rt); + + reg.r[rd] = reg.r[rs] & reg.r[rt]; +} + +void +Saddu(ulong inst) +{ + int rs, rt, rd; + + Get3(rs, rt, rd, inst); + if(trace) + itrace("addu\tr%d,r%d,r%d", rd, rs, rt); + + reg.r[rd] = reg.r[rs] + reg.r[rt]; +} + +void +Sadd(ulong inst) +{ + int rs, rt, rd; + + Get3(rs, rt, rd, inst); + if(trace) + itrace("add\tr%d,r%d,r%d", rd, rs, rt); + + reg.r[rd] = reg.r[rs] + reg.r[rt]; +} + +void +Ssubu(ulong inst) +{ + int rs, rt, rd; + + Get3(rs, rt, rd, inst); + if(trace) + itrace("subu\tr%d,r%d,r%d", rd, rs, rt); + + reg.r[rd] = reg.r[rs] - reg.r[rt]; +} + +void +Sor(ulong inst) +{ + int rs, rt, rd; + + Get3(rs, rt, rd, inst); + if(trace) + itrace("or\tr%d,r%d,r%d", rd, rs, rt); + + reg.r[rd] = reg.r[rs] | reg.r[rt]; +} + +void +Sxor(ulong inst) +{ + int rs, rt, rd; + + Get3(rs, rt, rd, inst); + if(trace) + itrace("or\tr%d,r%d,r%d", rd, rs, rt); + + reg.r[rd] = reg.r[rs] ^ reg.r[rt]; +} + +void +Sjr(ulong inst) +{ + ulong npc; + int rs; + Symbol s; + + rs = (inst>>21)&0x1f; + npc = reg.r[rs]; + + if(trace) + itrace("jr\t0x%lux", npc); + + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + if(calltree) { + if(rs == 31 || rs == 2) { + findsym(npc, CTEXT, &s); + Bprint(bioout, "%8lux return to %lux %s r1=%lux\n", + reg.pc, npc, s.name, reg.r[1]); + } + } + reg.pc = npc-4; +} + +void +Sjalr(ulong inst) +{ + ulong npc; + int rs, rd; + Symbol s; + + rs = (inst>>21)&0x1f; + rd = (inst>>11)&0x1f; + npc = reg.r[rs]; + + if(trace) + itrace("jalr\tr%d,r%d", rd, rs); + + reg.r[rd] = reg.pc+8; + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + + if(calltree) { + findsym(npc, CTEXT, &s); + if(rs == 31) + Bprint(bioout, "%8lux return to %8lux %s\n", + reg.pc, npc, s.name); + else { + printparams(&s, reg.r[29]); + Bputc(bioout, '\n'); + } + } + + reg.pc = npc-4; +} + +void +Sdivu(ulong inst) +{ + int rs, rt; + + Getrsrt(rs,rt,inst); + if(trace) + itrace("divu\tr%d,r%d", rs, rt); + + reg.mlo = (ulong)reg.r[rs]/(ulong)reg.r[rt]; + reg.mhi = (ulong)reg.r[rs]%(ulong)reg.r[rt]; +} + +void +Sdiv(ulong inst) +{ + int rs, rt; + + Getrsrt(rs,rt,inst); + if(trace) + itrace("div\tr%d,r%d", rs, rt); + + reg.mlo = reg.r[rs]/reg.r[rt]; + reg.mhi = reg.r[rs]%reg.r[rt]; +} + +void +Smfhi(ulong inst) +{ + int rd; + + rd = (inst>>11)&0x1ff; + if(trace) + itrace("mfhi\tr%d", rd); + + reg.r[rd] = reg.mhi; +} + +void +Smflo(ulong inst) +{ + int rd; + + rd = (inst>>11)&0x1ff; + if(trace) + itrace("mflo\tr%d", rd); + + reg.r[rd] = reg.mlo; +} + +void +Smult(ulong inst) +{ + int rs, rt; + Mul m; + + Getrsrt(rs,rt,inst); + if(trace) + itrace("mult\tr%d,r%d", rs,rt); + + m = mul(reg.r[rs], reg.r[rt]); + reg.mlo = m.lo; + reg.mhi = m.hi; +} + +void +Smultu(ulong inst) +{ + int rs, rt; + Mulu m; + + Getrsrt(rs,rt,inst); + if(trace) + itrace("multu\tr%d,r%d", rs,rt); + + m = mulu(reg.r[rs], reg.r[rt]); + reg.mlo = m.lo; + reg.mhi = m.hi; +} diff --git a/sys/src/cmd/vi/stats.c b/sys/src/cmd/vi/stats.c new file mode 100755 index 000000000..178111082 --- /dev/null +++ b/sys/src/cmd/vi/stats.c @@ -0,0 +1,251 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "mips.h" + +#define prof profvi +#define Percent(num, max) (((num)*100)/(max)) + +extern Inst itab[], ispec[], cop1[]; +Inst *tables[] = { itab, ispec, cop1, 0 }; + +void +isum(void) +{ + Inst *i; + int total, loads, stores, arith, branch, realarith; + int useddelay, taken, mipreg, syscall; + int ldsunused, ldsused, ltotal; + int pct, j; + + total = 0; + loads = 0; + stores = 0; + arith = 0; + branch = 0; + useddelay = 0; + taken = 0; + mipreg = 0; + syscall = 0; + realarith = 0; + + /* Compute the total so we can have percentages */ + for(i = itab; i->func; i++) + if(i->name && i->count) + total += i->count; + + for(i = ispec; i->func; i++) { + if(i->name && i->count) { + } + } + /* Compute the total so we can have percentages */ + for(j = 0; tables[j]; j++) { + for(i = tables[j]; i->func; i++) { + if(i->name && i->count) { + /* Dont count floating point twice */ + if(strcmp(i->name, "cop1") == 0) + i->count = 0; + else + total += i->count; + } + } + } + + Bprint(bioout, "\nInstruction summary.\n\n"); + + for(j = 0; tables[j]; j++) { + for(i =tables[j]; i->func; i++) { + if(i->name) { + /* This is gross */ + if(strcmp(i->name, INOPINST) == 0) + i->count -= nopcount; + if(i->count == 0) + continue; + pct = Percent(i->count, total); + if(pct != 0) + Bprint(bioout, "%-8ud %3d%% %s\n", + i->count, Percent(i->count, + total), i->name); + else + Bprint(bioout, "%-8ud %s\n", + i->count, i->name); + + + switch(i->type) { + default: + fatal(0, "isum bad stype %d\n", i->type); + case Iload: + loads += i->count; + break; + case Istore: + stores += i->count; + break; + case Iarith: + arith += i->count; + break; + case Ibranch: + branch += i->count; + taken += i->taken; + useddelay += i->useddelay; + break; + case Ireg: + mipreg += i->count; + break; + case Isyscall: + syscall += i->count; + break; + case Ifloat: + realarith += i->count; + break; + } + + } + } + } + + Bprint(bioout, "\n%-8ud Memory cycles\n", loads+stores+total); + Bprint(bioout, "%-8ud %3d%% Instruction cycles\n", + total, Percent(total, loads+stores+total)); + Bprint(bioout, "%-8ud %3d%% Data cycles\n\n", + loads+stores, Percent(loads+stores, loads+stores+total)); + + Bprint(bioout, "%-8ud %3d%% Stores\n", stores, Percent(stores, total)); + Bprint(bioout, "%-8ud %3d%% Loads\n", loads, Percent(loads, total)); + + /* Delay slots for loads/stores */ + ldsunused = nopcount-(branch-useddelay); + ldsused = loads-ldsunused; + ltotal = ldsused + ldsunused; + Bprint(bioout, " %-8ud %3d%% Delay slots\n", + ldsused, Percent(ldsused, ltotal)); + + Bprint(bioout, " %-8ud %3d%% Unused delay slots\n", + ldsunused, Percent(ldsunused, ltotal)); + + Bprint(bioout, "%-8ud %3d%% Arithmetic\n", + arith, Percent(arith, total)); + + Bprint(bioout, "%-8ud %3d%% Floating point\n", + realarith, Percent(realarith, total)); + + Bprint(bioout, "%-8ud %3d%% Mips special register load/stores\n", + mipreg, Percent(mipreg, total)); + + Bprint(bioout, "%-8ud %3d%% System calls\n", + syscall, Percent(syscall, total)); + + Bprint(bioout, "%-8ud %3d%% Branches\n", + branch, Percent(branch, total)); + + Bprint(bioout, " %-8ud %3d%% Branches taken\n", + taken, Percent(taken, branch)); + + Bprint(bioout, " %-8ud %3d%% Delay slots\n", + useddelay, Percent(useddelay, branch)); + + Bprint(bioout, " %-8ud %3d%% Unused delay slots\n", + branch-useddelay, Percent(branch-useddelay, branch)); + + Bprint(bioout, "%-8ud %3d%% Program total delay slots\n", + nopcount, Percent(nopcount, total)); +} + +void +tlbsum(void) +{ + if(tlb.on == 0) + return; + + Bprint(bioout, "\n\nTlb summary\n"); + + Bprint(bioout, "\n%-8d User entries\n", tlb.tlbsize); + Bprint(bioout, "%-8d Accesses\n", tlb.hit+tlb.miss); + Bprint(bioout, "%-8d Tlb hits\n", tlb.hit); + Bprint(bioout, "%-8d Tlb misses\n", tlb.miss); + Bprint(bioout, "%7d%% Hit rate\n", Percent(tlb.hit, tlb.hit+tlb.miss)); +} + +char *stype[] = { "Stack", "Text", "Data", "Bss" }; + +void +segsum(void) +{ + Segment *s; + int i; + + Bprint(bioout, "\n\nMemory Summary\n\n"); + Bprint(bioout, " Base End Resident References\n"); + for(i = 0; i < Nseg; i++) { + s = &memory.seg[i]; + Bprint(bioout, "%-5s %.8lux %.8lux %-8d %-8d\n", + stype[i], s->base, s->end, s->rss*BY2PG, s->refs); + } +} + +typedef struct Prof Prof; +struct Prof +{ + Symbol s; + long count; +}; +Prof prof[5000]; + +int +profcmp(void *va, void *vb) +{ + Prof *a, *b; + + a = va; + b = vb; + return b->count - a->count; +} + +void +iprofile(void) +{ + Prof *p, *n; + int i, b, e; + ulong total; + extern ulong textbase; + + i = 0; + p = prof; + if(textsym(&p->s, i) == 0) + return; + i++; + for(;;) { + n = p+1; + if(textsym(&n->s, i) == 0) + break; + b = (p->s.value-textbase)/PROFGRAN; + e = (n->s.value-textbase)/PROFGRAN; + while(b < e) + p->count += iprof[b++]; + i++; + p = n; + } + + qsort(prof, i, sizeof(Prof), profcmp); + + total = 0; + for(b = 0; b < i; b++) + total += prof[b].count; + + Bprint(bioout, " cycles %% symbol file\n"); + for(b = 0; b < i; b++) { + if(prof[b].count == 0) + continue; + + Bprint(bioout, "%8ld %3ld.%ld %-15s ", + prof[b].count, + 100*prof[b].count/total, + (1000*prof[b].count/total)%10, + prof[b].s.name); + + printsource(prof[b].s.value); + Bputc(bioout, '\n'); + } + memset(prof, 0, sizeof(Prof)*i); +} diff --git a/sys/src/cmd/vi/symbols.c b/sys/src/cmd/vi/symbols.c new file mode 100755 index 000000000..e3f885352 --- /dev/null +++ b/sys/src/cmd/vi/symbols.c @@ -0,0 +1,96 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "mips.h" + +#define STRINGSZ 128 + +/* + * print the value of dot as file:line + */ +void +printsource(long dot) +{ + char str[STRINGSZ]; + + if (fileline(str, STRINGSZ, dot)) + Bprint(bioout, "%s", str); +} + +void +printlocals(Symbol *fn, ulong fp) +{ + int i; + Symbol s; + + s = *fn; + for (i = 0; localsym(&s, i); i++) { + if (s.class != CAUTO) + continue; + Bprint(bioout, "\t%s=#%lux\n", s.name, getmem_4(fp-s.value)); + } +} + +void +printparams(Symbol *fn, ulong fp) +{ + int i; + Symbol s; + int first; + + fp += mach->szreg; /* skip saved pc */ + s = *fn; + for (first = i = 0; localsym(&s, i); i++) { + if (s.class != CPARAM) + continue; + if (first++) + Bprint(bioout, ", "); + Bprint(bioout, "%s=#%lux", s.name, getmem_4(fp+s.value)); + } + Bprint(bioout, ") "); +} +#define STARTSYM "_main" +#define FRAMENAME ".frame" + +void +stktrace(int modif) +{ + ulong pc, sp; + Symbol s, f; + int i; + char buf[512]; + + pc = reg.pc; + sp = reg.r[29]; + i = 0; + while (findsym(pc, CTEXT, &s)) { + if(strcmp(STARTSYM, s.name) == 0) { + Bprint(bioout, "%s() at #%llux\n", s.name, s.value); + break; + } + if (pc == s.value) /* at first instruction */ + f.value = 0; + else if (findlocal(&s, FRAMENAME, &f) == 0) + break; + if (s.type == 'L' || s.type == 'l' || pc <= s.value+4) + pc = reg.r[31]; + else pc = getmem_4(sp); + sp += f.value; + Bprint(bioout, "%s(", s.name); + printparams(&s, sp); + printsource(s.value); + Bprint(bioout, " called from "); + symoff(buf, sizeof(buf), pc-8, CTEXT); + Bprint(bioout, buf); + printsource(pc-8); + Bprint(bioout, "\n"); + if(modif == 'C') + printlocals(&s, sp); + if(++i > 40){ + Bprint(bioout, "(trace truncated)\n"); + break; + } + } +} diff --git a/sys/src/cmd/vi/syscall.c b/sys/src/cmd/vi/syscall.c new file mode 100755 index 000000000..7b977dd0d --- /dev/null +++ b/sys/src/cmd/vi/syscall.c @@ -0,0 +1,731 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "mips.h" + +#define REGSP 29 +#define REGRET 1 + +#define ODIRLEN 116 /* compatibility; used in _stat etc. */ +#define OERRLEN 64 /* compatibility; used in _stat etc. */ + +char errbuf[ERRMAX]; +ulong nofunc; + +#include "/sys/src/libc/9syscall/sys.h" + +char *sysctab[]={ + [SYSR1] "SYSR1", + [_ERRSTR] "_errstr", + [BIND] "Bind", + [CHDIR] "Chdir", + [CLOSE] "Close", + [DUP] "Dup", + [ALARM] "Alarm", + [EXEC] "Exec", + [EXITS] "Exits", + [_FSESSION] "_Fsession", + [FAUTH] "Fauth", + [_FSTAT] "_fstat", + [SEGBRK] "Segbrk", + [_MOUNT] "_Mount", + [OPEN] "Open", + [_READ] "_Read", + [OSEEK] "Oseek", + [SLEEP] "Sleep", + [_STAT] "_Stat", + [RFORK] "Rfork", + [_WRITE] "_Write", + [PIPE] "Pipe", + [CREATE] "Create", + [FD2PATH] "Fd2path", + [BRK_] "Brk_", + [REMOVE] "Remove", + [_WSTAT] "_Wstat", + [_FWSTAT] "_Fwstat", + [NOTIFY] "Notify", + [NOTED] "Noted", + [SEGATTACH] "Segattach", + [SEGDETACH] "Segdetach", + [SEGFREE] "Segfree", + [SEGFLUSH] "Segflush", + [RENDEZVOUS] "Rendezvous", + [UNMOUNT] "Unmount", + [_WAIT] "Wait", + [SEEK] "Seek", + [FVERSION] "Fversion", + [ERRSTR] "Errstr", + [STAT] "Stat", + [FSTAT] "Fstat", + [WSTAT] "Wstat", + [FWSTAT] "Fwstat", + [MOUNT] "Mount", + [AWAIT] "Await", + [PREAD] "Pread", + [PWRITE] "Pwrite", +}; + +void sys1(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0); } + +void +sys_errstr(void) +{ + ulong str; + + str = getmem_w(reg.r[REGSP]+4); + if(sysdbg) + itrace("errstr(0x%lux)", str); + + memio(errbuf, str, OERRLEN, MemWrite); + strcpy(errbuf, "no error"); + reg.r[REGRET] = 0; + +} + +void +syserrstr(void) +{ + ulong str; + uint n; + + str = getmem_w(reg.r[REGSP]+4); + n = getmem_w(reg.r[REGSP]+8); + if(sysdbg) + itrace("errstr(0x%lux, 0x%lux)", str, n); + + if(n > strlen(errbuf)+1) + n = strlen(errbuf)+1; + memio(errbuf, str, n, MemWrite); + strcpy(errbuf, "no error"); + reg.r[REGRET] = n; + +} + +void +sysfd2path(void) +{ + int n; + uint fd; + ulong str; + char buf[1024]; + + fd = getmem_w(reg.r[REGSP]+4); + str = getmem_w(reg.r[REGSP]+8); + n = getmem_w(reg.r[REGSP]+12); + if(sysdbg) + itrace("fd2path(0x%lux, 0x%lux, 0x%lux)", fd, str, n); + reg.r[REGRET] = -1; + if(n > sizeof buf){ + strcpy(errbuf, "buffer too big"); + return; + } + n = fd2path(fd, buf, sizeof buf); + if(n < 0) + errstr(buf, sizeof buf); + else + memio(errbuf, str, n, MemWrite); + reg.r[REGRET] = n; + +} + +void +sysbind(void) +{ + ulong pname, pold, flags; + char name[1024], old[1024]; + int n; + + pname = getmem_w(reg.r[REGSP]+4); + pold = getmem_w(reg.r[REGSP]+8); + flags = getmem_w(reg.r[REGSP]+12); + memio(name, pname, sizeof(name), MemReadstring); + memio(old, pold, sizeof(old), MemReadstring); + if(sysdbg) + itrace("bind(0x%lux='%s', 0x%lux='%s', 0x%lux)", name, name, old, old, flags); + + n = bind(name, old, flags); + if(n < 0) + errstr(errbuf, sizeof errbuf); + + reg.r[REGRET] = n; +} + +void +syschdir(void) +{ + char file[1024]; + int n; + ulong name; + + name = getmem_w(reg.r[REGSP]+4); + memio(file, name, sizeof(file), MemReadstring); + if(sysdbg) + itrace("chdir(0x%lux='%s', 0x%lux)", name, file); + + n = chdir(file); + if(n < 0) + errstr(errbuf, sizeof errbuf); + + reg.r[REGRET] = n; +} + +void +sysclose(void) +{ + int n; + ulong fd; + + fd = getmem_w(reg.r[REGSP]+4); + if(sysdbg) + itrace("close(%d)", fd); + + n = close(fd); + if(n < 0) + errstr(errbuf, sizeof errbuf); + reg.r[REGRET] = n; +} + +void +sysdup(void) +{ + int oldfd, newfd; + int n; + + oldfd = getmem_w(reg.r[REGSP]+4); + newfd = getmem_w(reg.r[REGSP]+8); + if(sysdbg) + itrace("dup(%d, %d)", oldfd, newfd); + + n = dup(oldfd, newfd); + if(n < 0) + errstr(errbuf, sizeof errbuf); + reg.r[REGRET] = n; +} + +void +sysexits(void) +{ + char buf[OERRLEN]; + ulong str; + + str = getmem_w(reg.r[REGSP]+4); + if(sysdbg) + itrace("exits(0x%lux)", str); + + count = 1; + if(str != 0) { + memio(buf, str, sizeof buf, MemRead); + Bprint(bioout, "exits(%s)\n", buf); + } + else + Bprint(bioout, "exits(0)\n"); +} + +void +sysopen(void) +{ + char file[1024]; + int n; + ulong mode, name; + + name = getmem_w(reg.r[REGSP]+4); + mode = getmem_w(reg.r[REGSP]+8); + memio(file, name, sizeof(file), MemReadstring); + if(sysdbg) + itrace("open(0x%lux='%s', 0x%lux)", name, file, mode); + + n = open(file, mode); + if(n < 0) + errstr(errbuf, sizeof errbuf); + + reg.r[REGRET] = n; +}; + +void +sysread(vlong offset) +{ + int fd; + ulong size, a; + char *buf, *p; + int n, cnt, c; + + fd = getmem_w(reg.r[REGSP]+4); + a = getmem_w(reg.r[REGSP]+8); + size = getmem_w(reg.r[REGSP]+12); + + buf = emalloc(size); + if(fd == 0) { + print("\nstdin>>"); + p = buf; + n = 0; + cnt = size; + while(cnt) { + c = Bgetc(bin); + if(c <= 0) + break; + *p++ = c; + n++; + cnt--; + if(c == '\n') + break; + } + } + else + n = pread(fd, buf, size, offset); + + if(n < 0) + errstr(errbuf, sizeof errbuf); + else + memio(buf, a, n, MemWrite); + + if(sysdbg) + itrace("read(%d, 0x%lux, %d, 0x%llx) = %d", fd, a, size, offset, n); + + free(buf); + reg.r[REGRET] = n; +} + +void +sys_read(void) +{ + sysread(-1LL); +} + +void +syspread(void) +{ + union { + vlong v; + ulong u[2]; + } o; + + o.u[0] = getmem_w(reg.r[REGSP]+16); + o.u[1] = getmem_w(reg.r[REGSP]+20); + sysread(o.v); +} + +void +sysseek(void) +{ + int fd; + ulong mode; + ulong retp; + union { + vlong v; + ulong u[2]; + } o; + + retp = getmem_w(reg.r[REGSP]+4); + fd = getmem_w(reg.r[REGSP]+8); + o.u[0] = getmem_w(reg.r[REGSP]+12); + o.u[1] = getmem_w(reg.r[REGSP]+16); + mode = getmem_w(reg.r[REGSP]+20); + if(sysdbg) + itrace("seek(%d, %lld, %d)", fd, o.v, mode); + + o.v = seek(fd, o.v, mode); + if(o.v < 0) + errstr(errbuf, sizeof errbuf); + + memio((char*)o.u, retp, sizeof(vlong), MemWrite); +} + +void +sysoseek(void) +{ + int fd, n; + ulong off, mode; + + fd = getmem_w(reg.r[REGSP]+4); + off = getmem_w(reg.r[REGSP]+8); + mode = getmem_w(reg.r[REGSP]+12); + if(sysdbg) + itrace("seek(%d, %lud, %d)", fd, off, mode); + + n = seek(fd, off, mode); + if(n < 0) + errstr(errbuf, sizeof errbuf); + + reg.r[REGRET] = n; +} + +void +sysrfork(void) +{ + int flag; + + flag = getmem_w(reg.r[REGSP]+4); + if(sysdbg) + itrace("rfork(%d)", flag); + if(flag & RFPROC) { + Bprint(bioout, "rfork: cannot create process, rfork(0x%.8ux)\n", flag); + exits(0); + } + reg.r[REGRET] = rfork(flag); +} + +void +syssleep(void) +{ + ulong len; + int n; + + len = getmem_w(reg.r[REGSP]+4); + if(sysdbg) + itrace("sleep(%d)", len); + + n = sleep(len); + if(n < 0) + errstr(errbuf, sizeof errbuf); + + reg.r[REGRET] = n; +} + +void +sys_stat(void) +{ + char nambuf[1024]; + char buf[ODIRLEN]; + ulong edir, name; + extern int _stat(char*, char*); /* old system call */ + int n; + + name = getmem_w(reg.r[REGSP]+4); + edir = getmem_w(reg.r[REGSP]+8); + memio(nambuf, name, sizeof(nambuf), MemReadstring); + if(sysdbg) + itrace("stat(0x%lux='%s', 0x%lux)", name, nambuf, edir); + + n = _stat(nambuf, buf); + if(n < 0) + errstr(errbuf, sizeof errbuf); + else + memio(buf, edir, ODIRLEN, MemWrite); + + reg.r[REGRET] = n; +} + +void +sysstat(void) +{ + char nambuf[1024]; + uchar buf[STATMAX]; + ulong edir, name; + int n; + + name = getmem_w(reg.r[REGSP]+4); + edir = getmem_w(reg.r[REGSP]+8); + n = getmem_w(reg.r[REGSP]+12); + memio(nambuf, name, sizeof(nambuf), MemReadstring); + if(sysdbg) + itrace("stat(0x%lux='%s', 0x%lux, 0x%lux)", name, nambuf, edir, n); + if(n > sizeof buf) + errstr(errbuf, sizeof errbuf); + else{ + n = stat(nambuf, buf, n); + if(n < 0) + errstr(errbuf, sizeof errbuf); + else + memio((char*)buf, edir, n, MemWrite); + } + reg.r[REGRET] = n; +} + +void +sys_fstat(void) +{ + char buf[ODIRLEN]; + ulong edir; + extern int _fstat(int, char*); /* old system call */ + int n, fd; + + fd = getmem_w(reg.r[REGSP]+4); + edir = getmem_w(reg.r[REGSP]+8); + if(sysdbg) + itrace("fstat(%d, 0x%lux)", fd, edir); + + n = _fstat(fd, buf); + if(n < 0) + errstr(errbuf, sizeof errbuf); + else + memio(buf, edir, ODIRLEN, MemWrite); + + reg.r[REGRET] = n; +} + +void +sysfstat(void) +{ + uchar buf[STATMAX]; + ulong edir; + int n, fd; + + fd = getmem_w(reg.r[REGSP]+4); + edir = getmem_w(reg.r[REGSP]+8); + n = getmem_w(reg.r[REGSP]+12); + if(sysdbg) + itrace("fstat(%d, 0x%lux, 0x%lux)", fd, edir, n); + + reg.r[REGRET] = -1; + if(n > sizeof buf){ + strcpy(errbuf, "stat buffer too big"); + return; + } + n = fstat(fd, buf, n); + if(n < 0) + errstr(errbuf, sizeof errbuf); + else + memio((char*)buf, edir, n, MemWrite); + reg.r[REGRET] = n; +} + +void +syswrite(vlong offset) +{ + int fd; + ulong size, a; + char *buf; + int n; + + fd = getmem_w(reg.r[REGSP]+4); + a = getmem_w(reg.r[REGSP]+8); + size = getmem_w(reg.r[REGSP]+12); + + Bflush(bioout); + buf = memio(0, a, size, MemRead); + n = pwrite(fd, buf, size, offset); + if(n < 0) + errstr(errbuf, sizeof errbuf); + if(sysdbg) + itrace("write(%d, %lux, %d, 0xllx) = %d", fd, a, size, offset, n); + free(buf); + + reg.r[REGRET] = n; +} + +void +sys_write(void) +{ + syswrite(-1LL); +} + +void +syspwrite(void) +{ + union { + vlong v; + ulong u[2]; + } o; + + o.u[0] = getmem_w(reg.r[REGSP]+16); + o.u[1] = getmem_w(reg.r[REGSP]+20); + syswrite(o.v); +} + +void +syspipe(void) +{ + int n, p[2]; + ulong fd; + + fd = getmem_w(reg.r[REGSP]+4); + if(sysdbg) + itrace("pipe(%lux)", fd); + + n = pipe(p); + if(n < 0) + errstr(errbuf, sizeof errbuf); + else { + putmem_w(fd, p[0]); + putmem_w(fd+4, p[1]); + } + reg.r[REGRET] = n; +} + +void +syscreate(void) +{ + char file[1024]; + int n; + ulong mode, name, perm; + + name = getmem_w(reg.r[REGSP]+4); + mode = getmem_w(reg.r[REGSP]+8); + perm = getmem_w(reg.r[REGSP]+12); + memio(file, name, sizeof(file), MemReadstring); + if(sysdbg) + itrace("create(0x%lux='%s', 0x%lux, 0x%lux)", name, file, mode, perm); + + n = create(file, mode, perm); + if(n < 0) + errstr(errbuf, sizeof errbuf); + + reg.r[REGRET] = n; +} + +void +sysbrk_(void) +{ + ulong addr, osize, nsize; + Segment *s; + + addr = getmem_w(reg.r[REGSP]+4); + if(sysdbg) + itrace("brk_(0x%lux)", addr); + + reg.r[REGRET] = -1; + if(addr < memory.seg[Data].base+datasize) { + strcpy(errbuf, "address below segment"); + return; + } + if(addr > memory.seg[Stack].base) { + strcpy(errbuf, "segment too big"); + return; + } + s = &memory.seg[Bss]; + if(addr > s->end) { + osize = ((s->end-s->base)/BY2PG)*sizeof(uchar*); + addr = ((addr)+(BY2PG-1))&~(BY2PG-1); + s->end = addr; + nsize = ((s->end-s->base)/BY2PG)*sizeof(uchar*); + s->table = erealloc(s->table, osize, nsize); + } + + reg.r[REGRET] = 0; +} + +void +sysremove(void) +{ + char nambuf[1024]; + ulong name; + int n; + + name = getmem_w(reg.r[REGSP]+4); + memio(nambuf, name, sizeof(nambuf), MemReadstring); + if(sysdbg) + itrace("remove(0x%lux='%s')", name, nambuf); + + n = remove(nambuf); + if(n < 0) + errstr(errbuf, sizeof errbuf); + reg.r[REGRET] = n; +} + +void +sysnotify(void) +{ + nofunc = getmem_w(reg.r[REGSP]+4); + if(sysdbg) + itrace("notify(0x%lux)\n", nofunc); + + reg.r[REGRET] = 0; +} + +void +syssegflush(void) +{ + int n; + ulong va; + + va = getmem_w(reg.r[REGSP]+4); + n = getmem_w(reg.r[REGSP]+8); + if(sysdbg) + itrace("segflush(va=0x%lux, n=%d)\n", va, n); + + reg.r[REGRET] = 0; +} + +void sysfversion(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0); } +void sysfsession(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0); } +void sysfauth(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0); } +void syswait(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0); } +void syswstat(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void sys_wstat(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void sysfwstat(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void sys_fwstat(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void sysnoted(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void syssegattach(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void syssegdetach(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void syssegfree(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void sysrendezvous(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void sysunmount(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void sysfork(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void sysforkpgrp(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void syssegbrk(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void _sysmount(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void sysalarm(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void sysexec(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void sysmount(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} +void sysawait(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);} + +void (*systab[])(void) ={ + [SYSR1] sys1, + [_ERRSTR] sys_errstr, + [BIND] sysbind, + [CHDIR] syschdir, + [CLOSE] sysclose, + [DUP] sysdup, + [ALARM] sysalarm, + [EXEC] sysexec, + [EXITS] sysexits, + [_FSESSION] sysfsession, + [FAUTH] sysfauth, + [_FSTAT] sys_fstat, + [SEGBRK] syssegbrk, + [_MOUNT] _sysmount, + [OPEN] sysopen, + [_READ] sys_read, + [OSEEK] sysoseek, + [SLEEP] syssleep, + [_STAT] sys_stat, + [RFORK] sysrfork, + [_WRITE] sys_write, + [PIPE] syspipe, + [CREATE] syscreate, + [FD2PATH] sysfd2path, + [BRK_] sysbrk_, + [REMOVE] sysremove, + [_WSTAT] sys_wstat, + [_FWSTAT] sys_fwstat, + [NOTIFY] sysnotify, + [NOTED] sysnoted, + [SEGATTACH] syssegattach, + [SEGDETACH] syssegdetach, + [SEGFREE] syssegfree, + [SEGFLUSH] syssegflush, + [RENDEZVOUS] sysrendezvous, + [UNMOUNT] sysunmount, + [_WAIT] syswait, + [SEEK] sysseek, + [FVERSION] sysfversion, + [ERRSTR] syserrstr, + [STAT] sysstat, + [FSTAT] sysfstat, + [WSTAT] syswstat, + [FWSTAT] sysfwstat, + [MOUNT] sysmount, + [AWAIT] sysawait, + [PREAD] syspread, + [PWRITE] syspwrite, +}; + +void +Ssyscall(ulong inst) +{ + int call; + + USED(inst); + call = reg.r[REGRET]; + if(call < 0 || call > PWRITE || systab[call] == nil) { + Bprint(bioout, "Bad system call\n"); + dumpreg(); + } + if(trace) + itrace("sysc\t%s", sysctab[call]); + + (*systab[call])(); + Bflush(bioout); +} diff --git a/sys/src/cmd/vi/vi.c b/sys/src/cmd/vi/vi.c new file mode 100755 index 000000000..bc31b5bf1 --- /dev/null +++ b/sys/src/cmd/vi/vi.c @@ -0,0 +1,507 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern +#include "mips.h" + +char *file = "v.out"; +int datasize; +ulong textbase; +Biobuf bp, bi; +Fhdr fhdr; + +void +main(int argc, char **argv) +{ + int pid; + + argc--; + argv++; + + bioout = &bp; + bin = &bi; + Binit(bioout, 1, OWRITE); + Binit(bin, 0, OREAD); + + tlb.on = 1; + tlb.tlbsize = 24; + + if(argc) { + pid = atoi(argv[0]); + if(pid != 0) { + procinit(pid); + cmd(); + } + file = argv[0]; + } + argc--; + argv++; + + text = open(file, OREAD); + if(text < 0) + fatal(1, "open text '%s'", file); + + Bprint(bioout, "vi\n"); + inithdr(text); + initstk(argc, argv); + + reg.fd[dreg(24)] = 0.0; /* Normally initialised by the kernel */ + reg.ft[24] = FPd; + reg.fd[dreg(26)] = 0.5; + reg.ft[26] = FPd; + reg.fd[dreg(28)] = 1.0; + reg.ft[28] = FPd; + reg.fd[dreg(30)] = 2.0; + reg.ft[30] = FPd; + cmd(); +} + +void +initmap() +{ + ulong t, d, b, bssend; + Segment *s; + + t = (fhdr.txtaddr+fhdr.txtsz+(BY2PG-1)) & ~(BY2PG-1); + d = (t + fhdr.datsz + (BY2PG-1)) & ~(BY2PG-1); + bssend = t + fhdr.datsz + fhdr.bsssz; + b = (bssend + (BY2PG-1)) & ~(BY2PG-1); + + s = &memory.seg[Text]; + s->type = Text; + s->base = fhdr.txtaddr - fhdr.hdrsz; + s->end = t; + s->fileoff = fhdr.txtoff - fhdr.hdrsz; + s->fileend = s->fileoff + fhdr.txtsz; + s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*)); + + iprof = emalloc(((s->end-s->base)/PROFGRAN)*sizeof(long)); + textbase = s->base; + + s = &memory.seg[Data]; + s->type = Data; + s->base = t; + s->end = t+(d-t); + s->fileoff = fhdr.datoff; + s->fileend = s->fileoff + fhdr.datsz; + datasize = fhdr.datsz; + s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*)); + + s = &memory.seg[Bss]; + s->type = Bss; + s->base = d; + s->end = d+(b-d); + s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*)); + + s = &memory.seg[Stack]; + s->type = Stack; + s->base = STACKTOP-STACKSIZE; + s->end = STACKTOP; + s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*)); + + reg.pc = fhdr.entry; +} + +void +inithdr(int fd) +{ + Symbol s; + + extern Machdata mipsmach; + + seek(fd, 0, 0); + if (!crackhdr(fd, &fhdr)) + fatal(0, "read text header"); + + if(fhdr.type != FMIPS && fhdr.type != FMIPS2BE) + fatal(0, "bad magic number: %d %d", fhdr.type, FMIPS); + + if (syminit(fd, &fhdr) < 0) + fatal(0, "%r\n"); + + symmap = loadmap(symmap, fd, &fhdr); + if (mach->sbreg && lookup(0, mach->sbreg, &s)) + mach->sb = s.value; + machdata = &mipsmach; +} + +ulong +greg(int f, ulong off) +{ + int n; + ulong l; + uchar wd[BY2WD]; + + seek(f, off, 0); + n = read(f, wd, BY2WD); + if(n != BY2WD) + fatal(1, "read register"); + + l = wd[0]<<24; + l |= wd[1]<<16; + l |= wd[2]<<8; + l |= wd[3]; + return l; +} + +ulong +roff[] = { + REGOFF(r1), REGOFF(r2), REGOFF(r3), + REGOFF(r4), REGOFF(r5), REGOFF(r6), + REGOFF(r7), REGOFF(r8), REGOFF(r9), + REGOFF(r10), REGOFF(r11), REGOFF(r12), + REGOFF(r13), REGOFF(r14), REGOFF(r15), + REGOFF(r16), REGOFF(r17), REGOFF(r18), + REGOFF(r19), REGOFF(r20), REGOFF(r21), + REGOFF(r22), REGOFF(r23), REGOFF(r24), + REGOFF(r25), REGOFF(r26), REGOFF(r27), + REGOFF(r28) +}; + +void +seginit(int fd, Segment *s, int idx, ulong vastart, ulong vaend) +{ + int n; + + while(vastart < vaend) { + seek(fd, vastart, 0); + s->table[idx] = emalloc(BY2PG); + n = read(fd, s->table[idx], BY2PG); + if(n != BY2PG) + fatal(1, "data read"); + vastart += BY2PG; + idx++; + } +} + +void +procinit(int pid) +{ + char *p; + Segment *s; + int n, m, sg, i; + ulong vastart, vaend; + char mfile[128], tfile[128], sfile[1024]; + + sprint(mfile, "/proc/%d/mem", pid); + sprint(tfile, "/proc/%d/text", pid); + sprint(sfile, "/proc/%d/segment", pid); + + text = open(tfile, OREAD); + if(text < 0) + fatal(1, "open text %s", tfile); + inithdr(text); + + sg = open(sfile, OREAD); + if(sg < 0) + fatal(1, "open text %s", sfile); + + n = read(sg, sfile, sizeof(sfile)); + if(n >= sizeof(sfile)) + fatal(0, "segment file buffer too small"); + close(sg); + + m = open(mfile, OREAD); + if(m < 0) + fatal(1, "open %s", mfile); + + initmap(); + p = strstr(sfile, "Data"); + if(p == 0) + fatal(0, "no data"); + + vastart = strtoul(p+9, 0, 16); + vaend = strtoul(p+18, 0, 16); + s = &memory.seg[Data]; + if(s->base != vastart || s->end != vaend) { + s->base = vastart; + s->end = vaend; + free(s->table); + s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*)); + } + seginit(m, s, 0, vastart, vaend); + + p = strstr(sfile, "Bss"); + if(p == 0) + fatal(0, "no bss"); + + vastart = strtoul(p+9, 0, 16); + vaend = strtoul(p+18, 0, 16); + s = &memory.seg[Bss]; + if(s->base != vastart || s->end != vaend) { + s->base = vastart; + s->end = vaend; + free(s->table); + s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*)); + } + seginit(m, s, 0, vastart, vaend); + + reg.pc = greg(m, REGOFF(pc)); + reg.r[29] = greg(m, REGOFF(sp)); + reg.r[30] = greg(m, REGOFF(r30)); + reg.r[31] = greg(m, REGOFF(r31)); + + reg.mhi = greg(m, REGOFF(hi)); + reg.mlo = greg(m, REGOFF(lo)); + + for(i = 1; i < 29; i++) + reg.r[i] = greg(m, roff[i-1]); + + s = &memory.seg[Stack]; + vastart = reg.r[29] & ~(BY2PG-1); + seginit(m, s, (vastart-s->base)/BY2PG, vastart, STACKTOP); + close(m); + Bprint(bioout, "vi\n"); +} + +void +reset(void) +{ + int i, l, m; + Segment *s; + Breakpoint *b; + + memset(®, 0, sizeof(Registers)); + reg.fd[dreg(24)] = 0.0; /* Normally initialised by the kernel */ + reg.ft[24] = FPd; + reg.fd[dreg(26)] = 0.5; + reg.ft[26] = FPd; + reg.fd[dreg(28)] = 1.0; + reg.ft[28] = FPd; + reg.fd[dreg(30)] = 2.0; + reg.ft[30] = FPd; + + for(i = 0; i > Nseg; i++) { + s = &memory.seg[i]; + l = ((s->end-s->base)/BY2PG)*sizeof(uchar*); + for(m = 0; m < l; m++) + if(s->table[m]) + free(s->table[m]); + free(s->table); + } + free(iprof); + memset(&memory, 0, sizeof(memory)); + + for(b = bplist; b; b = b->next) + b->done = b->count; +} + +void +initstk(int argc, char *argv[]) +{ + ulong size; + ulong sp, ap; + int i; + char *p; + + initmap(); + sp = STACKTOP - 4; + + /* Build exec stack */ + size = strlen(file)+1+BY2WD+BY2WD+BY2WD; + for(i = 0; i < argc; i++) + size += strlen(argv[i])+BY2WD+1; + + sp -= size; + sp &= ~3; + reg.r[29] = sp; + reg.r[1] = STACKTOP-4; /* Plan 9 profiling clock */ + + /* Push argc */ + putmem_w(sp, argc+1); + sp += BY2WD; + + /* Compute sizeof(argv) and push argv[0] */ + ap = sp+((argc+1)*BY2WD)+BY2WD; + putmem_w(sp, ap); + sp += BY2WD; + + /* Build argv[0] string into stack */ + for(p = file; *p; p++) + putmem_b(ap++, *p); + + putmem_b(ap++, '\0'); + + /* Loop through pushing the arguments */ + for(i = 0; i < argc; i++) { + putmem_w(sp, ap); + sp += BY2WD; + for(p = argv[i]; *p; p++) + putmem_b(ap++, *p); + putmem_b(ap++, '\0'); + } + /* Null terminate argv */ + putmem_w(sp, 0); + +} + +void +fatal(int syserr, char *fmt, ...) +{ + char buf[ERRMAX], *s; + va_list arg; + + va_start(arg, fmt); + vseprint(buf, buf+sizeof(buf), fmt, arg); + va_end(arg); + s = "vi: %s\n"; + if(syserr) + s = "vi: %s: %r\n"; + fprint(2, s, buf); + exits(buf); +} + +void +itrace(char *fmt, ...) +{ + char buf[128]; + va_list arg; + + va_start(arg, fmt); + vseprint(buf, buf+sizeof(buf), fmt, arg); + va_end(arg); + Bprint(bioout, "%8lux %.8lux %s\n", reg.pc, reg.ir, buf); +} + +void +dumpreg(void) +{ + int i; + + Bprint(bioout, "PC #%-8lux SP #%-8lux HI #%-8lux LO #%-8lux\n", + reg.pc, reg.r[29], reg.mhi, reg.mlo); + + for(i = 0; i < 32; i++) { + if((i%4) == 0 && i != 0) + Bprint(bioout, "\n"); + Bprint(bioout, "R%-2d #%-8lux ", i, reg.r[i]); + } + Bprint(bioout, "\n"); +} + +void +dumpfreg(void) +{ + int i; + char buf[64]; + + i = 0; + while(i < 32) { + ieeesftos(buf, sizeof(buf), reg.di[i]); + Bprint(bioout, "F%-2d %s\t", i, buf); + i++; + + ieeesftos(buf, sizeof(buf), reg.di[i]); + Bprint(bioout, "\t\t\tF%-2d %s\n", i, buf); + i++; + } +} + +void +dumpdreg(void) +{ + int i; + char buf[64]; + + i = 0; + while(i < 32) { + if(reg.ft[i] == FPd) + ieeedftos(buf, sizeof(buf), reg.di[i] ,reg.di[i+1]); + else + ieeedftos(buf, sizeof(buf), reg.di[i+1] ,reg.di[i]); + Bprint(bioout, "F%-2d %s\t\t\t", i, buf); + i += 2; + + if(reg.ft[i] == FPd) + ieeedftos(buf, sizeof(buf), reg.di[i] ,reg.di[i+1]); + else + ieeedftos(buf, sizeof(buf), reg.di[i+1] ,reg.di[i]); + Bprint(bioout, "F%-2d %s\n", i, buf); + i += 2; + } +} + +void * +emalloc(ulong size) +{ + void *a; + + a = malloc(size); + if(a == 0) + fatal(0, "no memory"); + + memset(a, 0, size); + return a; +} + +void * +erealloc(void *a, ulong oldsize, ulong size) +{ + void *n; + + n = malloc(size); + if(n == 0) + fatal(0, "no memory"); + memset(n, 0, size); + if(size > oldsize) + size = oldsize; + memmove(n, a, size); + return n; +} + +Mulu +mulu(ulong u1, ulong u2) +{ + ulong lo1, lo2, hi1, hi2, lo, hi, t1, t2, t; + + lo1 = u1 & 0xffff; + lo2 = u2 & 0xffff; + hi1 = u1 >> 16; + hi2 = u2 >> 16; + + lo = lo1 * lo2; + t1 = lo1 * hi2; + t2 = lo2 * hi1; + hi = hi1 * hi2; + t = lo; + lo += t1 << 16; + if(lo < t) + hi++; + t = lo; + lo += t2 << 16; + if(lo < t) + hi++; + hi += (t1 >> 16) + (t2 >> 16); + return (Mulu){lo, hi}; +} + +Mul +mul(long l1, long l2) +{ + Mulu m; + ulong t, lo, hi; + int sign; + + sign = 0; + if(l1 < 0){ + sign ^= 1; + l1 = -l1; + } + if(l2 < 0){ + sign ^= 1; + l2 = -l2; + } + m = mulu(l1, l2); + lo = m.lo; + hi = m.hi; + if(sign){ + t = lo = ~lo; + hi = ~hi; + lo++; + if(lo < t) + hi++; + } + return (Mul){lo, hi}; +} + |