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/ki |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/ki')
-rwxr-xr-x | sys/src/cmd/ki/bpt.c | 129 | ||||
-rwxr-xr-x | sys/src/cmd/ki/cmd.c | 632 | ||||
-rwxr-xr-x | sys/src/cmd/ki/float.c | 445 | ||||
-rwxr-xr-x | sys/src/cmd/ki/icache.c | 18 | ||||
-rwxr-xr-x | sys/src/cmd/ki/ki.c | 484 | ||||
-rwxr-xr-x | sys/src/cmd/ki/mem.c | 240 | ||||
-rwxr-xr-x | sys/src/cmd/ki/mkfile | 27 | ||||
-rwxr-xr-x | sys/src/cmd/ki/run.c | 1411 | ||||
-rwxr-xr-x | sys/src/cmd/ki/sparc.h | 236 | ||||
-rwxr-xr-x | sys/src/cmd/ki/stats.c | 214 | ||||
-rwxr-xr-x | sys/src/cmd/ki/symbols.c | 97 | ||||
-rwxr-xr-x | sys/src/cmd/ki/syscall.c | 729 |
12 files changed, 4662 insertions, 0 deletions
diff --git a/sys/src/cmd/ki/bpt.c b/sys/src/cmd/ki/bpt.c new file mode 100755 index 000000000..6647034a5 --- /dev/null +++ b/sys/src/cmd/ki/bpt.c @@ -0,0 +1,129 @@ +#include <u.h> +#include <libc.h> +#include <ctype.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "sparc.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, "%s", 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, "%s", 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, "%s", 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, "%s", buf); + break; + + case Equal: + Bprint(bioout, "0x%lux,%d:be at ", b->addr, b->count); + symoff(buf, sizeof(buf), b->addr, CDATA); + Bprint(bioout, "%s", 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/ki/cmd.c b/sys/src/cmd/ki/cmd.c new file mode 100755 index 000000000..095ae0271 --- /dev/null +++ b/sys/src/cmd/ki/cmd.c @@ -0,0 +1,632 @@ +#include <u.h> +#include <libc.h> +#include <ctype.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "sparc.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) +{ + cp = nextc(cp); + switch(*cp) { + default: + Bprint(bioout, "?\n"); + break; + + case 'c': + case 'C': + stktrace(*cp); + break; + + case 'b': + dobplist(); + break; + + case 'r': + dumpreg(); + break; + + case 'R': + dumpreg(); + /* fall through */ + + case 'f': + dumpfreg(); + break; + + case 'F': + dumpdreg(); + break; + + case 'q': + exits(0); + break; + + case 'Q': + isum(); + segsum(); + break; + + case 't': + cp++; + switch(*cp) { + default: + Bprint(bioout, ":t[0sic]\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; + } + break; + + case 'i': + cp++; + switch(*cp) { + default: + Bprint(bioout, "$i[isa]\n"); + break; + case 'i': + isum(); + break; + case 's': + segsum(); + break; + case 'a': + isum(); + 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, "%-3d ", (int)(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); + Bprint(bioout, "%s", 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': + case 'i': + inc = machdata->das(symmap, dot, fmt, str, sizeof(str)); + if (inc < 0) { + Bprint(bioout, "ki: %r\n"); + return 0; + } + c = Bprint(bioout, "\t%s", 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("ki\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[1] = dot; + return; + } + if(strcmp(cp, "y") == 0) { + reg.Y = dot; + return; + } + if(strcmp(cp, "psr") == 0) { + reg.psr = 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/ki/float.c b/sys/src/cmd/ki/float.c new file mode 100755 index 000000000..a73472901 --- /dev/null +++ b/sys/src/cmd/ki/float.c @@ -0,0 +1,445 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "sparc.h" + +void +ldf(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("ldf\tf%d,0x%lux(r%d) ea=%lux",rd, ea, rs1, ea+reg.r[rs1]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("ldf\tf%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); + } + + reg.di[rd] = getmem_w(ea); +} + +void +lddf(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("lddf\tf%d,0x%lux(r%d) ea=%lux", + rd, ea, rs1, ea+reg.r[rs1]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("lddf\tf%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); + } + + if(ea&7) { + Bprint(bioout, "mem_address_not_aligned [load addr %.8lux]\n", ea); + longjmp(errjmp, 0); + } + if(rd&1) + undef(ir); + + reg.di[rd] = getmem_w(ea); + reg.di[rd+1] = getmem_w(ea+4); +} + +void +stf(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("stf\tf%d,0x%lux(r%d) %lux=%g", + rd, ea, rs1, ea+reg.r[rs1], reg.fl[rd]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("stf\tf%d,[r%d+r%d] %lux=%lux", + rd, rs1, rs2, ea, reg.r[rd]); + } + + putmem_w(ea, reg.di[rd]); +} + +void +stdf(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("stdf\tf%d,0x%lux(r%d) %lux=%g", + rd, ea, rs1, ea+reg.r[rs1], reg.fl[rd]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("stdf\tf%d,[r%d+r%d] %lux=%lux", + rd, rs1, rs2, ea, reg.r[rd]); + } + + if(ea&7) { + Bprint(bioout, "mem_address_not_aligned [store addr %.8lux]\n", ea); + longjmp(errjmp, 0); + } + if(rd&1) + undef(ir); + + putmem_w(ea, reg.di[rd]); + putmem_w(ea+4, reg.di[rd+1]); +} + +void +fcmp(ulong ir) +{ + int fc, rd, rs1, rs2; + + getrop23(ir); + USED(rd); + SET(fc); + switch((ir>>5)&0x1FF) { + default: + undef(ir); + case 0x51: /* fcmps */ + if(trace) + itrace("fcmps\tf%d,f%d", rs1, rs2); + if(isNaN(reg.fl[rs1]) || isNaN(reg.fl[rs2])) { + fc = 3; + break; + } + if(reg.fl[rs1] == reg.fl[rs2]) { + fc = 0; + break; + } + if(reg.fl[rs1] < reg.fl[rs2]) { + fc = 1; + break; + } + if(reg.fl[rs1] > reg.fl[rs2]) { + fc = 2; + break; + } + print("ki: fcmp error\n"); + break; + case 0x52: + if(trace) + itrace("fcmpd\tf%d,f%d", rs1, rs2); + rs1 >>= 1; + rs2 >>= 1; + if(isNaN(reg.fd[rs1]) || isNaN(reg.fd[rs2])) { + fc = 3; + break; + } + if(reg.fd[rs1] == reg.fd[rs2]) { + fc = 0; + break; + } + if(reg.fd[rs1] < reg.fd[rs2]) { + fc = 1; + break; + } + if(reg.fd[rs1] > reg.fd[rs2]) { + fc = 2; + break; + } + print("ki: fcmp error\n"); + break; + case 0x55: /* fcmpes */ + if(trace) + itrace("fcmpes\tf%d,f%d", rs1, rs2); + rs1 >>= 1; + rs2 >>= 2; + if(isNaN(reg.fl[rs1]) || isNaN(reg.fl[rs2])) { + Bprint(bioout, "invalid_fp_register\n"); + longjmp(errjmp, 0); + } + if(reg.fl[rs1] == reg.fl[rs2]) { + fc = 0; + break; + } + if(reg.fl[rs1] < reg.fl[rs2]) { + fc = 1; + break; + } + if(reg.fl[rs1] > reg.fl[rs2]) { + fc = 2; + break; + } + print("ki: fcmp error\n"); + break; + case 0x56: + if(trace) + itrace("fcmped\tf%d,f%d", rs1, rs2); + if(isNaN(reg.fd[rs1]) || isNaN(reg.fd[rs2])) { + Bprint(bioout, "invalid_fp_register\n"); + longjmp(errjmp, 0); + } + if(reg.fd[rs1] == reg.fd[rs2]) { + fc = 0; + break; + } + if(reg.fd[rs1] < reg.fd[rs2]) { + fc = 1; + break; + } + if(reg.fd[rs1] > reg.fd[rs2]) { + fc = 2; + break; + } + print("ki: fcmp error\n"); + break; + + } + reg.fpsr = (reg.fpsr&~(0x3<<10)) | (fc<<10); +} + +void +fbcc(ulong ir) +{ + char *op; + ulong npc; + int takeit, fc, ba, anul; + + fc = (reg.fpsr>>10)&3; + ba = 0; + SET(op, takeit); + switch((ir>>25)&0x0F) { + case 0: + op = "fbn"; + takeit = 0; + break; + case 1: + op = "fbne"; + takeit = fc == FP_L || fc == FP_G || fc == FP_U; + break; + case 2: + op = "fblg"; + takeit = fc == FP_L || fc == FP_G; + break; + case 3: + op = "fbul"; + takeit = fc == FP_L || fc == FP_U; + break; + case 4: + op = "fbl"; + takeit = fc == FP_L; + break; + case 5: + op = "fbug"; + takeit = fc == FP_U || fc == FP_G; + break; + case 6: + op = "fbg"; + takeit = fc == FP_G; + break; + case 7: + op = "fbu"; + takeit = fc == FP_U; + break; + case 8: + op = "fba"; + ba = 1; + takeit = 1; + break; + case 9: + op = "fbe"; + takeit = fc == FP_E; + break; + case 10: + op = "fbue"; + takeit = fc == FP_E || fc == FP_U; + break; + case 11: + op = "fbge"; + takeit = fc == FP_E || fc == FP_G; + break; + case 12: + op = "fbuge"; + takeit = fc == FP_E || fc == FP_G || fc == FP_U; + break; + case 13: + op = "fble"; + takeit = fc == FP_E || fc == FP_L; + break; + case 14: + op = "fbule"; + takeit = fc == FP_E || fc == FP_L || fc == FP_U; + break; + case 15: + op = "fbo"; + takeit = fc == FP_E || fc == FP_L || fc == FP_G; + break; + } + + npc = ir & 0x3FFFFF; + if(npc & (1<<21)) + npc |= ~((1<<22)-1); + npc = (npc<<2) + reg.pc; + + anul = ir&ANUL; + if(trace) { + if(anul) + itrace("%s,a\t%lux", op, npc); + else + itrace("%s\t%lux", op, npc); + } + + if(takeit == 0) { + reg.pc += 4; + if(anul == 0) { + reg.ir = ifetch(reg.pc); + delay(reg.pc+4); + } + else + anulled++; + return; + } + + ci->taken++; + if(ba && anul) { + reg.pc = npc-4; + anulled++; + return; + } + reg.ir = ifetch(reg.pc+4); + delay(npc); + reg.pc = npc-4; +} + +void +farith(ulong ir) +{ + char *op; + long v; + int rd, rs1, rs2, fmt; + + fmt = 0; + getrop23(ir); + switch((ir>>5)&0x1FF) { + default: + undef(ir); + case 0x41: + reg.fl[rd] = reg.fl[rs1] + reg.fl[rs2]; + op = "fadds"; + break; + case 0x42: + reg.fd[rd>>1] = reg.fd[rs1>>1] + reg.fd[rs2>>1]; + op = "faddd"; + break; + case 0x45: + reg.fl[rd] = reg.fl[rs1] - reg.fl[rs2]; + op = "fsubs"; + break; + case 0x46: + reg.fd[rd>>1] = reg.fd[rs1>>1] - reg.fd[rs2>>1]; + op = "fsubd"; + break; + case 0x4d: + if(reg.fl[rs2] == 0.0) { + Bprint(bioout, "fp_exception DZ\n"); + longjmp(errjmp, 0); + } + reg.fl[rd] = reg.fl[rs1] / reg.fl[rs2]; + op = "fdivs"; + break; + case 0x4e: + if(reg.fd[rs2>>1] == 0.0) { + Bprint(bioout, "fp_exception DZ\n"); + longjmp(errjmp, 0); + } + reg.fd[rd>>1] = reg.fd[rs1>>1] / reg.fd[rs2>>1]; + op = "fdivd"; + break; + case 0x49: + reg.fl[rd] = reg.fl[rs1] * reg.fl[rs2]; + op = "fmuls"; + break; + case 0x4a: + reg.fd[rd>>1] = reg.fd[rs1>>1] * reg.fd[rs2>>1]; + op = "fmuld"; + break; + case 0xc4: + reg.fl[rd] = (long)reg.di[rs2]; + fmt = 1; + op = "fitos"; + break; + case 0xc8: + reg.fd[rd>>1] = (long)reg.di[rs2]; + fmt = 1; + op = "fitod"; + break; + case 0xd1: + v = reg.fl[rs2]; + reg.di[rd] = v; + fmt = 1; + op = "fstoi"; + break; + case 0xd2: + v = reg.fd[rs2>>1]; + reg.di[rd] = v; + fmt = 1; + op = "fdtoi"; + break; + case 0x01: + reg.di[rd] = reg.di[rs2]; + fmt = 1; + op = "fmovs"; + break; + case 0x05: + reg.fl[rd] = -reg.fl[rs2]; + fmt = 1; + op = "fnegs"; + break; + case 0x09: + reg.fl[rd] = fabs(reg.fl[rs2]); + fmt = 1; + op = "fabss"; + break; + case 0xc9: + reg.fd[rd>>1] = reg.fl[rs2]; + fmt = 1; + op = "fstod"; + break; + case 0xc6: + reg.fl[rd] = reg.fd[rs2>>1]; + fmt = 1; + op = "fdtos"; + break; + } + + if(trace) { + switch(fmt) { + case 0: + itrace("%s\tf%d,f%d,f%d", op, rs1, rs2, rd); + break; + case 1: + itrace("%s\tf%d,f%d", op, rs2, rd); + break; + } + } +} diff --git a/sys/src/cmd/ki/icache.c b/sys/src/cmd/ki/icache.c new file mode 100755 index 000000000..0e1ecb45c --- /dev/null +++ b/sys/src/cmd/ki/icache.c @@ -0,0 +1,18 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "sparc.h" + +void +icacheinit(void) +{ +} + +void +updateicache(ulong addr) +{ + USED(addr); +} + diff --git a/sys/src/cmd/ki/ki.c b/sys/src/cmd/ki/ki.c new file mode 100755 index 000000000..6a07e7be5 --- /dev/null +++ b/sys/src/cmd/ki/ki.c @@ -0,0 +1,484 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern +#include "sparc.h" + +char *file = "k.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); + + 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, "ki\n"); + inithdr(text); + initstk(argc, argv); + + reg.fd[13] = 0.5; /* Normally initialised by the kernel */ + reg.fd[12] = 0.0; + reg.fd[14] = 1.0; + reg.fd[15] = 2.0; + cmd(); +} + +void +initmap(void) +{ + + 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 sparcmach; + + seek(fd, 0, 0); + if (!crackhdr(fd, &fhdr)) + fatal(0, "read text header"); + + if(fhdr.type != FSPARC) + fatal(0, "bad magic number"); + + 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 = &sparcmach; + asstype = ASUNSPARC; +} + +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[1] = greg(m, REGOFF(sp)); + reg.r[30] = greg(m, REGOFF(r30)); + reg.r[31] = greg(m, REGOFF(r31)); + + for(i = 1; i < 29; i++) + reg.r[i] = greg(m, roff[i-1]); + + s = &memory.seg[Stack]; + vastart = reg.r[1] & ~(BY2PG-1); + seginit(m, s, (vastart-s->base)/BY2PG, vastart, STACKTOP); + close(m); + Bprint(bioout, "ki\n"); +} + +void +reset(void) +{ + int i, l, m; + Segment *s; + Breakpoint *b; + + memset(®, 0, sizeof(Registers)); + reg.fd[13] = 0.5; /* Normally initialised by the kernel */ + reg.fd[12] = 0.0; + reg.fd[14] = 1.0; + reg.fd[15] = 2.0; + 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, sp, ap; + int i; + char *p; + + initmap(); + sp = STACKTOP - 4; + + /* Build exec stack */ + size = strlen(file)+1+BY2WD+BY2WD+(BY2WD*2); + for(i = 0; i < argc; i++) + size += strlen(argv[i])+BY2WD+1; + + sp -= size; + sp &= ~7; + reg.r[1] = sp; + reg.r[7] = 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 = "ki: %s\n"; + if(syserr) + s = "ki: %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 Y #%-8lux PSR #%-8lux\n", + reg.pc, reg.r[1], reg.Y, reg.psr); + + 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, "\tF%-2d %s\n", i, buf); + i++; + } +} + +void +dumpdreg(void) +{ + int i; + char buf[64]; + + i = 0; + while(i < 32) { + ieeedftos(buf, sizeof(buf), reg.di[i] ,reg.di[i+1]); + Bprint(bioout, "F%-2d %s\t", i, buf); + i += 2; + ieeedftos(buf, sizeof(buf), reg.di[i] ,reg.di[i+1]); + Bprint(bioout, "\tF%-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}; +} diff --git a/sys/src/cmd/ki/mem.c b/sys/src/cmd/ki/mem.c new file mode 100755 index 000000000..0ab7d580b --- /dev/null +++ b/sys/src/cmd/ki/mem.c @@ -0,0 +1,240 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "sparc.h" + +extern ulong textbase; + +ulong +ifetch(ulong addr) +{ + uchar *va; + + if(addr&3) { + Bprint(bioout, "instruction_address_not_aligned [addr %.8lux]\n", addr); + longjmp(errjmp, 0); + } + + if(icache.on) + updateicache(addr); + + va = vaddr(addr); + iprof[(addr-textbase)/PROFGRAN]++; + + 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, "mem_address_not_aligned [load addr %.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, "mem_address_not_aligned [load addr %.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, "mem_address_not_aligned [store addr %.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, "mem_address_not_aligned [store addr %.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 * +vaddr(ulong addr) +{ + Segment *s, *es; + int off, foff, l, n; + uchar **p, *a; + + 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; + } + } + } + Bprint(bioout, "data_access_MMU_miss [addr 0x%.8lux]\n", addr); + longjmp(errjmp, 0); + return 0; /*to stop compiler whining*/ +} diff --git a/sys/src/cmd/ki/mkfile b/sys/src/cmd/ki/mkfile new file mode 100755 index 000000000..b0434f635 --- /dev/null +++ b/sys/src/cmd/ki/mkfile @@ -0,0 +1,27 @@ +</$objtype/mkfile + +TARG=ki +OFILES= ki.$O\ + run.$O\ + mem.$O\ + syscall.$O\ + stats.$O\ + icache.$O\ + symbols.$O\ + cmd.$O\ + bpt.$O\ + float.$O\ + +HFILES=sparc.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/ki/run.c b/sys/src/cmd/ki/run.c new file mode 100755 index 000000000..269eaa44c --- /dev/null +++ b/sys/src/cmd/ki/run.c @@ -0,0 +1,1411 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "sparc.h" + +void add(ulong); +void and(ulong); +void or(ulong); +void xor(ulong); +void sub(ulong); +void andn(ulong); +void xnor(ulong); +void subcc(ulong); +void sll(ulong); +void srl(ulong); +void sra(ulong); +void jmpl(ulong); +void andcc(ulong); +void xorcc(ulong); +void andncc(ulong); +void wry(ulong); +void rdy(ulong); +void mulscc(ulong); +void fcmp(ulong); +void farith(ulong); +void addcc(ulong); +void addx(ulong); +void addxcc(ulong); +void orcc(ulong); +void orncc(ulong); +void xnorcc(ulong); +void orn(ulong); + +Inst op2[] = { + { add, "add", Iarith }, + { and, "and", Iarith }, + { or, "or", Iarith }, + { xor, "xor", Iarith }, + { sub, "sub", Iarith }, + { andn, "andn", Iarith }, + { orn, "orn", Inop }, + { xnor, "xnor", Iarith }, + { addx, "addx", Iarith }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { addcc, "addcc", Iarith }, + { andcc, "andcc", Iarith }, + { orcc, "orcc", Iarith }, + { xorcc, "xorcc", Iarith }, + { subcc, "subcc", Iarith }, + { andncc, "andncc",Iarith }, + { orncc, "orncc", Iarith }, + { xnorcc, "xnorcc",Iarith }, + { addxcc, "addxcc",Iarith }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { mulscc, "mulscc", Iarith }, + { sll, "sll", Iarith }, + { srl, "srl", Iarith }, + { sra, "sra", Iarith }, + { rdy, "rdy", Ireg }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { wry, "wry", Ireg }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { farith, "farith", Ifloat }, + { fcmp, "fcmp", Ifloat }, + { undef, "" }, + { undef, "" }, + { jmpl, "jmpl", Ibranch }, + { undef, "" }, + { ta, "ta", Isyscall }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { 0 } +}; + +void st(ulong); +void stb(ulong); +void sth(ulong); +void ld(ulong); +void ldub(ulong); +void ldsb(ulong); +void lduh(ulong); +void stf(ulong); +void ldf(ulong); +void ldsh(ulong); +void std(ulong); +void ldd(ulong); +void ldstub(ulong); +void swap(ulong); +void lddf(ulong); +void stdf(ulong); + +Inst op3[] = { + { ld, "ld", Iload }, + { ldub, "ldub", Iload }, + { lduh, "lduh", Iload }, + { ldd, "ldd", Iload }, + { st, "st", Istore }, + { stb, "stb", Istore }, + { sth, "sth", Istore }, + { std, "std", Istore }, + { undef, "" }, + { ldsb, "ldsb", Iload }, + { ldsh, "ldsh", Iload }, + { undef, "" }, + { undef, "" }, + { ldstub, "ldstub", Iload }, + { undef, "" }, + { swap, "swap", Iload }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { ldf, "ldf", Ifloat }, + { undef, "" }, + { undef, "" }, + { lddf, "lddf", Ifloat }, + { stf, "stf", Ifloat }, + { undef, "" }, + { undef, "" }, + { stdf, "stdf", Ifloat }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { undef, "" }, + { 0 } +}; + +void sethi(ulong); +void bicc(ulong); +void fbcc(ulong); +void call(ulong); + +Inst op0[] = { + { undef, "" }, + { undef, "" }, + { bicc, "bicc", Ibranch }, + { undef, "" }, + { sethi, "sethi",Iarith }, + { undef, "" }, + { fbcc, "fbcc", Ibranch }, + { undef, "" }, + /* This is a fake and connot be reached by op0 decode */ + { call, "call", Ibranch }, + { 0 } +}; + +void call(ulong); + +void +run(void) +{ + do { + reg.r[0] = 0; + reg.ir = ifetch(reg.pc); + switch(reg.ir>>30) { + case 0: + ci = &op0[(reg.ir>>22)&0x07]; + ci->count++; + (*ci->func)(reg.ir); + break; + case 1: + ci = &op0[8]; + ci->count++; + call(reg.ir); + break; + case 2: + ci = &op2[(reg.ir>>19)&0x3f]; + ci->count++; + (*ci->func)(reg.ir); + break; + case 3: + ci = &op3[(reg.ir>>19)&0x3f]; + ci->count++; + (*ci->func)(reg.ir); + break; + } + reg.pc += 4; + if(bplist) + brkchk(reg.pc, Instruction); + }while(--count); +} + +void +ilock(int rd) +{ + ulong ir; + + ir = getmem_4(reg.pc+4); + switch(ir>>30) { + case 0: + case 1: + break; + case 2: + if(((ir>>20)&0x1f) == 0x1a) /* floating point */ + break; + case 3: + if(rd == ((ir>>14)&0x1f)) { + loadlock++; + break; + } + if(ir&IMMBIT) + break; + if(rd == (ir&0x1f)) + loadlock++; + break; + } +} + +void +delay(ulong npc) +{ + ulong opc; + + reg.r[0] = 0; + if(reg.ir != NOP) + ci->useddelay++; + switch(reg.ir>>30) { + case 0: + ci = &op0[(reg.ir>>22)&0x07]; + ci->count++; + (*ci->func)(reg.ir); + break; + case 1: + ci = &op0[8]; + ci->count++; + call(reg.ir); + break; + case 2: + ci = &op2[(reg.ir>>19)&0x3f]; + ci->count++; + opc = reg.pc; + reg.pc = npc-4; + (*ci->func)(reg.ir); + reg.pc = opc; + break; + case 3: + ci = &op3[(reg.ir>>19)&0x3f]; + ci->count++; + opc = reg.pc; + reg.pc = npc-4; + (*ci->func)(reg.ir); + reg.pc = opc; + break; + } +} + +void +undef(ulong ir) +{ +/* Bprint(bioout, "op=%d op2=%d op3=%d\n", ir>>30, (ir>>21)&0x7, (ir>>19)&0x3f); */ + Bprint(bioout, "illegal_instruction IR #%.8lux\n", ir); + longjmp(errjmp, 0); +} + +void +sub(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("sub\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("sub\tr%d,r%d,r%d", rs1, rs2, rd); + } + reg.r[rd] = reg.r[rs1] - v; +} + +void +sll(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("sll\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]&0x1F; + if(trace) + itrace("sll\tr%d,r%d,r%d", rs1, rs2, rd); + } + reg.r[rd] = reg.r[rs1] << v; +} + +void +srl(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("srl\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("srl\tr%d,r%d,r%d", rs1, rs2, rd); + } + reg.r[rd] = (ulong)reg.r[rs1] >> v; +} + +void +sra(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("sra\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("sra\tr%d,r%d,r%d", rs1, rs2, rd); + } + if(reg.r[rs1]&SIGNBIT) + reg.r[rd] = reg.r[rs1]>>v | ~((1<<(32-v))-1); + else + reg.r[rd] = reg.r[rs1]>>v; +} + +void +subcc(ulong ir) +{ + long v; + int b31rs1, b31op2, b31res, r, rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("subcc\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("subcc\tr%d,r%d,r%d", rs1, rs2, rd); + } + r = reg.r[rs1] - v; + reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); + if(r == 0) + reg.psr |= PSR_z; + if(r < 0) + reg.psr |= PSR_n; + + b31rs1 = reg.r[rs1]>>31; + b31op2 = v>>31; + b31res = r>>31; + + if((b31rs1 & ~b31op2 & ~b31res)|(~b31rs1 & b31op2 & b31res)) + reg.psr |= PSR_v; + + if((~b31rs1 & b31op2)|(b31res & (~b31rs1|b31op2))) + reg.psr |= PSR_c; + + reg.r[rd] = r; + +} + +void +add(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("add\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("add\tr%d,r%d,r%d", rs1, rs2, rd); + } + reg.r[rd] = reg.r[rs1] + v; +} + +void +addcc(ulong ir) +{ + long v, r; + int rd, rs1, rs2, b31rs1, b31op2, b31r; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("addcc\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("addcc\tr%d,r%d,r%d", rs1, rs2, rd); + } + r = reg.r[rs1] + v; + reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); + if(r == 0) + reg.psr |= PSR_z; + if(r < 0) + reg.psr |= PSR_n; + + b31rs1 = reg.r[rs1]>>31; + b31op2 = v>>31; + b31r = r>>31; + if((b31rs1 & b31op2 & ~b31r)|(~b31rs1 & ~b31op2 & b31r)) + reg.psr |= PSR_v; + if((b31rs1 & b31op2) | (~b31r & (b31rs1 | b31op2))) + reg.psr |= PSR_c; + + reg.r[rd] = r; +} + +void +addx(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("addx\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("addx\tr%d,r%d,r%d", rs1, rs2, rd); + } + if(reg.psr&PSR_c) + v++; + reg.r[rd] = reg.r[rs1] + v; +} + +void +addxcc(ulong ir) +{ + long r, v; + int rd, rs1, rs2, b31rs1, b31op2, b31r; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("addxcc\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("addxcc\tr%d,r%d,r%d", rs1, rs2, rd); + } + if(reg.psr&PSR_c) + v++; + + r = reg.r[rs1] + v; + reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); + if(r == 0) + reg.psr |= PSR_z; + if(r < 0) + reg.psr |= PSR_n; + + b31rs1 = reg.r[rs1]>>31; + b31op2 = v>>31; + b31r = r>>31; + if((b31rs1 & b31op2 & ~b31r)|(~b31rs1 & ~b31op2 & b31r)) + reg.psr |= PSR_v; + if((b31rs1 & b31op2) | (~b31r & (b31rs1 | b31op2))) + reg.psr |= PSR_c; + + reg.r[rd] = r; +} + +void +wry(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(rd != 0) + undef(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("wry\tr%d,#0x%x,Y", rs1, v); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("wry\tr%d,r%d,Y", rs1, rs2); + } + reg.Y = reg.r[rs1] + v; +} + +void +rdy(ulong ir) +{ + int rd, rs1, rs2; + + getrop23(ir); + USED(rs2); + if(rs1 != 0) + undef(ir); + + if(trace) + itrace("rdy\tY,r%d", rd); + + reg.r[rd] = reg.Y; +} + +void +and(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("and\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("and\tr%d,r%d,r%d", rs1, rs2, rd); + } + reg.r[rd] = reg.r[rs1] & v; +} + +void +andcc(ulong ir) +{ + long v, r; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("andcc\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("andcc\tr%d,r%d,r%d", rs1, rs2, rd); + } + r = reg.r[rs1] & v; + reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); + if(r == 0) + reg.psr |= PSR_z; + if(r < 0) + reg.psr |= PSR_n; + + reg.r[rd] = r; +} + +void +orcc(ulong ir) +{ + long v, r; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("orcc\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("orcc\tr%d,r%d,r%d", rs1, rs2, rd); + } + r = reg.r[rs1] | v; + reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); + if(r == 0) + reg.psr |= PSR_z; + if(r < 0) + reg.psr |= PSR_n; + + reg.r[rd] = r; +} + +void +mulscc(ulong ir) +{ + int b, n, v, rd, rs1, rs2; + long o1, o2, r, b31o1, b31o2, b31r; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(o2, ir); + if(trace) + itrace("mulscc\tr%d,#0x%x,r%d", rs1, o2, rd); + } + else { + o2 = reg.r[rs2]; + if(trace) + itrace("mulscc\tr%d,r%d,r%d", rs1, rs2, rd); + } + o1 = reg.r[rs1]>>1; + n = reg.psr&PSR_n ? 1 : 0; + v = reg.psr&PSR_v ? 1 : 0; + + o1 |= (n ^ v)<<31; + if((reg.Y&1) == 0) + o2 = 0; + + r = o1 + o2; + reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); + if(r == 0) + reg.psr |= PSR_z; + if(r < 0) + reg.psr |= PSR_n; + + b31o1 = o1>>31; + b31o2 = o2>>31; + b31r = r>>31; + if((b31o1 & b31o2 & ~b31r) | (~b31o1 & ~b31o2 & b31r)) + reg.psr |= PSR_v; + if((b31o1 & b31o2) | (~b31r & (b31o1 | b31o2))) + reg.psr |= PSR_c; + + b = reg.r[rs1]&1; + reg.Y = (reg.Y>>1)|(b<<31); + reg.r[rd] = r; +} + +void +or(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("or\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("or\tr%d,r%d,r%d", rs1, rs2, rd); + } + reg.r[rd] = reg.r[rs1] | v; +} + +void +xor(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("xor\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("xor\tr%d,r%d,r%d", rs1, rs2, rd); + } + reg.r[rd] = reg.r[rs1] ^ v; +} + +void +xorcc(ulong ir) +{ + long v, r; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("xorcc\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("xorcc\tr%d,r%d,r%d", rs1, rs2, rd); + } + r = reg.r[rs1] ^ v; + reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); + if(r == 0) + reg.psr |= PSR_z; + if(r < 0) + reg.psr |= PSR_n; + + reg.r[rd] = r; +} + +void +andn(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("andn\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("andn\tr%d,r%d,r%d", rs1, rs2, rd); + } + reg.r[rd] = reg.r[rs1] & ~v; +} + +void +andncc(ulong ir) +{ + long v, r; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("andncc\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("andncc\tr%d,r%d,r%d", rs1, rs2, rd); + } + r = reg.r[rs1] & ~v; + reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); + if(r == 0) + reg.psr |= PSR_z; + if(r < 0) + reg.psr |= PSR_n; + + reg.r[rd] = r; +} + +void +orn(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(rd == 0 && rs1 == 0) /* ken used orn r0,r0,r0 as nop */ + nopcount++; + + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("orn\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("orn\tr%d,r%d,r%d", rs1, rs2, rd); + } + reg.r[rd] = reg.r[rs1] | ~v; +} + +void +orncc(ulong ir) +{ + long r, v; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("orncc\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("orncc\tr%d,r%d,r%d", rs1, rs2, rd); + } + r = reg.r[rs1] | ~v; + reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); + if(r == 0) + reg.psr |= PSR_z; + if(r < 0) + reg.psr |= PSR_n; + + reg.r[rd] = r; +} + +void +xnor(ulong ir) +{ + long v; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("xnor\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("xnor\tr%d,r%d,r%d", rs1, rs2, rd); + } + reg.r[rd] = reg.r[rs1] ^ ~v; +} + +void +xnorcc(ulong ir) +{ + long v, r; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(v, ir); + if(trace) + itrace("xnorcc\tr%d,#0x%x,r%d", rs1, v, rd); + } + else { + v = reg.r[rs2]; + if(trace) + itrace("xnorcc\tr%d,r%d,r%d", rs1, rs2, rd); + } + r = reg.r[rs1] ^ ~v; + reg.psr &= ~(PSR_z|PSR_n|PSR_c|PSR_v); + if(r == 0) + reg.psr |= PSR_z; + if(r < 0) + reg.psr |= PSR_n; + + reg.r[rd] = r; +} + +void +st(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("st\tr%d,0x%lux(r%d) %lux=%lux", + rd, ea, rs1, ea+reg.r[rs1], reg.r[rd]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("st\tr%d,[r%d+r%d] %lux=%lux", + rd, rs1, rs2, ea, reg.r[rd]); + } + + putmem_w(ea, reg.r[rd]); +} + +void +std(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("std\tr%d,0x%lux(r%d) %lux=%lux", + rd, ea, rs1, ea+reg.r[rs1], reg.r[rd]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("std\tr%d,[r%d+r%d] %lux=%lux", + rd, rs1, rs2, ea, reg.r[rd]); + } + + putmem_w(ea, reg.r[rd]); + putmem_w(ea+4, reg.r[rd+1]); +} + +void +stb(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("stb\tr%d,0x%lux(r%d) %lux=%lux", + rd, ea, rs1, ea+reg.r[rs1], reg.r[rd]&0xff); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("stb\tr%d,[r%d+r%d] %lux=%lux", + rd, rs1, rs2, ea, reg.r[rd]&0xff); + } + + putmem_b(ea, reg.r[rd]); +} + +void +sth(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("sth\tr%d,0x%lux(r%d) %lux=%lux", + rd, ea, rs1, ea+reg.r[rs1], reg.r[rd]&0xffff); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("sth\tr%d,[r%d+r%d] %lux=%lux", + rd, rs1, rs2, ea, reg.r[rd]&0xffff); + } + + putmem_h(ea, reg.r[rd]); +} + +void +ld(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("ld\tr%d,0x%lux(r%d) ea=%lux",rd, ea, rs1, ea+reg.r[rs1]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("ld\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); + } + + reg.r[rd] = getmem_w(ea); + ilock(rd); +} + +void +swap(ulong ir) +{ + ulong t, ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("swap\tr%d,0x%lux(r%d) ea=%lux", + rd, ea, rs1, ea+reg.r[rs1]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("swap\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); + } + + t = reg.r[rd]; + reg.r[rd] = getmem_w(ea); + putmem_w(ea, t); +} + +void +ldd(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("ldd\tr%d,0x%lux(r%d) ea=%lux",rd, ea, rs1, ea+reg.r[rs1]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("ldd\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); + } + + reg.r[rd] = getmem_w(ea); + reg.r[rd+1] = getmem_w(ea+4); +} + +void +ldub(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("ldub\tr%d,0x%lux(r%d) ea=%lux", + rd, ea, rs1, ea+reg.r[rs1]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("ldub\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); + } + + reg.r[rd] = getmem_b(ea) & 0xff; + ilock(rd); +} + +void +ldstub(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("ldstub\tr%d,0x%lux(r%d) ea=%lux", + rd, ea, rs1, ea+reg.r[rs1]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("ldstub\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); + } + + reg.r[rd] = getmem_b(ea) & 0xff; + putmem_b(ea, 0xff); +} + +void +ldsb(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("ldsb\tr%d,0x%lux(r%d) ea=%lux", + rd, ea, rs1, ea+reg.r[rs1]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("ldsb\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); + } + + reg.r[rd] = (schar)getmem_b(ea); + ilock(rd); +} + +void +lduh(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("lduh\tr%d,0x%lux(r%d) ea=%lux", + rd, ea, rs1, ea+reg.r[rs1]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("lduh\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); + } + + reg.r[rd] = getmem_h(ea) & 0xffff; + ilock(rd); +} + +void +ldsh(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("ldsh\tr%d,0x%lux(r%d) ea=%lux", + rd, ea, rs1, ea+reg.r[rs1]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("ldsh\tr%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); + } + + reg.r[rd] = (short)getmem_h(ea); + ilock(rd); +} + +void +sethi(ulong ir) +{ + int rd; + ulong v; + + rd = (ir>>25)&0x1f; + v = (ir&0x3FFFFF)<<10; + + if(rd == 0) + nopcount++; + + if(trace) + itrace("sethi\t0x%lux,r%d", v, rd); + + reg.r[rd] = v; +} + +void +call(ulong ir) +{ + Symbol s; + ulong npc; + + npc = (ir<<2) + reg.pc; + if(trace) + itrace("call\t%lux", npc); + + ci->taken++; + reg.r[15] = reg.pc; + reg.ir = ifetch(reg.pc+4); + delay(npc); + + if(calltree) { + findsym(npc, CTEXT, &s); + Bprint(bioout, "%8lux %s(", reg.pc, s.name); + printparams(&s, reg.r[1]); + Bprint(bioout, "from "); + printsource(reg.pc); + Bputc(bioout, '\n'); + } + npc -= 4; + reg.pc = npc; +} + +void +jmpl(ulong ir) +{ + ulong ea, o; + Symbol s; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + o = ea; + if(trace) + itrace("jmpl\t0x%lux(r%d),r%d", ea, rs1, rd); + + ea += reg.r[rs1]; + if(calltree && rd == 0 && o == 8) { + findsym(ea-4, CTEXT, &s); + Bprint(bioout, "%8lux return to %lux %s r7=%lux\n", + reg.pc, ea-4, s.name, reg.r[7]); + } + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("jmpl\t[r%d+r%d],r%d", rs1, rs2, rd); + } + + ci->taken++; + reg.r[rd] = reg.pc; + reg.ir = ifetch(reg.pc+4); + delay(ea); + reg.pc = ea-4; +} + +void +bicc(ulong ir) +{ + char *op; + ulong npc, anul, ba; + int takeit, z, v, n, c; + + SET(op, takeit); + ba = 0; + switch((ir>>25)&0x0F) { + case 0: + op = "bn"; + takeit = 0; + break; + case 1: + op = "be"; + takeit = reg.psr&PSR_z; + break; + case 2: + op = "ble"; + z = reg.psr&PSR_z ? 1 : 0; + v = reg.psr&PSR_v ? 1 : 0; + n = reg.psr&PSR_n ? 1 : 0; + takeit = z | (n ^ v); + break; + case 3: + op = "bl"; + v = reg.psr&PSR_v ? 1 : 0; + n = reg.psr&PSR_n ? 1 : 0; + takeit = n ^ v; + break; + case 4: + op = "bleu"; + z = reg.psr&PSR_z ? 1 : 0; + c = reg.psr&PSR_c ? 1 : 0; + takeit = c | z; + break; + case 5: + op = "bcs"; + takeit = reg.psr&PSR_c; + break; + case 6: + op = "bneg"; + takeit = reg.psr&PSR_n; + break; + case 7: + op = "bvs"; + takeit = reg.psr&PSR_v; + break; + case 8: + op = "ba"; + ba = 1; + takeit = 1; + break; + case 9: + op = "bne"; + takeit = !(reg.psr&PSR_z); + break; + case 10: + op = "bg"; + z = reg.psr&PSR_z ? 1 : 0; + v = reg.psr&PSR_v ? 1 : 0; + n = reg.psr&PSR_n ? 1 : 0; + takeit = !(z | (n ^ v)); + break; + case 11: + op = "bge"; + v = reg.psr&PSR_v ? 1 : 0; + n = reg.psr&PSR_n ? 1 : 0; + takeit = !(n ^ v); + break; + case 12: + op = "bgu"; + z = reg.psr&PSR_z ? 1 : 0; + c = reg.psr&PSR_c ? 1 : 0; + takeit = !(c | z); + break; + case 13: + op = "bcc"; + takeit = !(reg.psr&PSR_c); + break; + case 14: + op = "bpos"; + takeit = !(reg.psr&PSR_n); + break; + case 15: + op = "bvc"; + takeit = !(reg.psr&PSR_v); + break; + } + + npc = ir & 0x3FFFFF; + if(npc & (1<<21)) + npc |= ~((1<<22)-1); + npc = (npc<<2) + reg.pc; + + anul = ir&ANUL; + if(trace) { + if(anul) + itrace("%s,a\t%lux", op, npc); + else + itrace("%s\t%lux", op, npc); + } + + if(takeit == 0) { + reg.pc += 4; + if(anul == 0) { + reg.ir = ifetch(reg.pc); + delay(reg.pc+4); + } + else + anulled++; + return; + } + + ci->taken++; + if(ba && anul) { + anulled++; + reg.pc = npc-4; + return; + } + reg.ir = ifetch(reg.pc+4); + delay(npc); + reg.pc = npc-4; +} diff --git a/sys/src/cmd/ki/sparc.h b/sys/src/cmd/ki/sparc.h new file mode 100755 index 000000000..1501f9e0f --- /dev/null +++ b/sys/src/cmd/ki/sparc.h @@ -0,0 +1,236 @@ +/* + * sparc sim.h + * + * The integer instruction side of this emulator is portable if sizeof(long) >= 4 + * Floating point emulation however is not. Assumptions made are: + * sizeof(ulong) == sizeof(float) + * sizeof(ulong)*2 == sizeof(double) + * bits of floating point in memory may be reversed lsw/msw + * unions of double & 2*float & 2*long have no padding + */ +#include "/sparc/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 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, + Inop, +}; + +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 Y; + ulong psr; + ulong fpsr; + + union { + double fd[16]; + float fl[32]; + ulong di[32]; + }; +}; + +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); +void itrace(char *, ...); +void segsum(void); +void ta(ulong); +char* memio(char*, ulong, int, int); +ulong getmem_w(ulong); +ulong ifetch(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); +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 initstk(int, char**); +void initmap(void); +void inithdr(int); +void reset(void); +void dobplist(void); +void procinit(int); +void printsource(long); +void printparams(Symbol *, ulong); +void printlocals(Symbol *, ulong); +void stktrace(int); +void delay(ulong); +void iprofile(void); + +/* Globals */ +Extern Registers reg; +Extern Memory memory; +Extern int text; +Extern int trace; +Extern int sysdbg; +Extern int calltree; +Extern Icache icache; +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 Inst *ci; +Extern ulong *iprof; +Extern ulong loadlock; +Extern ulong anulled; +extern int datasize; +extern int printcol; +Extern Map *symmap; + +/* Plan9 Kernel constants */ +#define BY2PG 4096 +#define BY2WD 4 +#define UTZERO 0x1000 +#define TSTKSIZ 32 +#define TSTACKTOP 0x10000000 +#define STACKTOP (TSTACKTOP-TSTKSIZ*BY2PG) +#define STACKSIZE (4*1024*1024) + +#define ANUL (1<<29) +#define PROFGRAN 4 +#define NOP 0x80300000 +#define SIGNBIT 0x80000000 +#define IMMBIT (1<<13) +#define getrop23(i) rd = (i>>25)&0x1f; rs1 = (i>>14)&0x1f; rs2 = i&0x1f; +#define ximm(xx, ii) xx = ii&0x1FFF; if(xx&0x1000) xx |= ~0x1FFF + +#define PSR_n (1<<23) +#define PSR_z (1<<22) +#define PSR_v (1<<21) +#define PSR_c (1<<20) + +#define FP_U 3 +#define FP_L 1 +#define FP_G 2 +#define FP_E 0 diff --git a/sys/src/cmd/ki/stats.c b/sys/src/cmd/ki/stats.c new file mode 100755 index 000000000..dc441e692 --- /dev/null +++ b/sys/src/cmd/ki/stats.c @@ -0,0 +1,214 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "sparc.h" + +#define prof profki +#define Percent(num, max) (((num)*100)/(max)) + +extern Inst op0[], op2[], op3[]; +Inst *tables[] = { op0, op2, op3, 0 }; + +void +isum(void) +{ + Inst *i; + int pct, j; + int total, loads, stores, arith, branch; + int useddelay, taken, sparcreg, syscall, realarith; + + total = 0; + loads = 0; + stores = 0; + arith = 0; + branch = 0; + useddelay = 0; + taken = 0; + sparcreg = 0; + syscall = 0; + realarith = 0; + + /* 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) + 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) { + 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: + sparcreg += i->count; + break; + case Isyscall: + syscall += i->count; + break; + case Ifloat: + realarith += i->count; + break; + case Inop: + arith += i->count; + i->count -= nopcount; + break; + } + } + } + } + + total += anulled; + 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, "%-8lud %3ld%% Annulled branch cycles\n", + anulled, Percent(anulled, 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)); + + Bprint(bioout, " %-8ud Store stall\n", stores*2); + + Bprint(bioout, " %-8lud Load stall\n", loadlock); + + 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%% Sparc special register load/stores\n", + sparcreg, Percent(sparcreg, 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", + nopcount, Percent(nopcount, branch)); + + Bprint(bioout, "%-8ud %3d%% Program total delay slots\n", + nopcount, Percent(nopcount, total)); +} + +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/ki/symbols.c b/sys/src/cmd/ki/symbols.c new file mode 100755 index 000000000..8c23d5c14 --- /dev/null +++ b/sys/src/cmd/ki/symbols.c @@ -0,0 +1,97 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "sparc.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[1]; + 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[15]; + 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/ki/syscall.c b/sys/src/cmd/ki/syscall.c new file mode 100755 index 000000000..685ccabf5 --- /dev/null +++ b/sys/src/cmd/ki/syscall.c @@ -0,0 +1,729 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "sparc.h" + +#define REGSP 1 +#define REGRET 7 + + +#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", + [PREAD] "Pread", + [PWRITE] "Pwrite", + [AWAIT] "Await", +}; + +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 sysawait(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0); } +void sysfversion(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0); } +void sys_fsession(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 sys_wait(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 (*systab[])(void) ={ + [SYSR1] sys1, + [_ERRSTR] sys_errstr, + [BIND] sysbind, + [CHDIR] syschdir, + [CLOSE] sysclose, + [DUP] sysdup, + [ALARM] sysalarm, + [EXEC] sysexec, + [EXITS] sysexits, + [_FSESSION] sys_fsession, + [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] sys_wait, + [SEEK] sysseek, + [FVERSION] sysfversion, + [ERRSTR] syserrstr, + [STAT] sysstat, + [FSTAT] sysfstat, + [WSTAT] syswstat, + [FWSTAT] sysfwstat, + [PREAD] syspread, + [PWRITE] syspwrite, + [AWAIT] sysawait, +}; + +void +ta(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("ta\t$0+R0\t%s", sysctab[call]); + + (*systab[call])(); + Bflush(bioout); +} |