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/5i |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/5i')
-rwxr-xr-x | sys/src/cmd/5i/5i.c | 270 | ||||
-rwxr-xr-x | sys/src/cmd/5i/arm.h | 240 | ||||
-rwxr-xr-x | sys/src/cmd/5i/bpt.c | 128 | ||||
-rwxr-xr-x | sys/src/cmd/5i/cmd.c | 635 | ||||
-rwxr-xr-x | sys/src/cmd/5i/float.c | 203 | ||||
-rwxr-xr-x | sys/src/cmd/5i/icache.c | 17 | ||||
-rwxr-xr-x | sys/src/cmd/5i/mem.c | 285 | ||||
-rwxr-xr-x | sys/src/cmd/5i/mkfile | 26 | ||||
-rwxr-xr-x | sys/src/cmd/5i/run.c | 948 | ||||
-rwxr-xr-x | sys/src/cmd/5i/stats.c | 199 | ||||
-rwxr-xr-x | sys/src/cmd/5i/symbols.c | 95 | ||||
-rwxr-xr-x | sys/src/cmd/5i/syscall.c | 807 |
12 files changed, 3853 insertions, 0 deletions
diff --git a/sys/src/cmd/5i/5i.c b/sys/src/cmd/5i/5i.c new file mode 100755 index 000000000..554a9f2cc --- /dev/null +++ b/sys/src/cmd/5i/5i.c @@ -0,0 +1,270 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include "arm.h" + +#include <tos.h> + +char* file = "5.out"; +int datasize; +ulong textbase; +Biobuf bp, bi; +Fhdr fhdr; + +void +main(int argc, char **argv) +{ + + argc--; + argv++; + + bioout = &bp; + bin = &bi; + Binit(bioout, 1, OWRITE); + Binit(bin, 0, OREAD); + + tlb.on = 1; + tlb.tlbsize = 24; + + if(argc) + file = argv[0]; + argc--; + argv++; + + text = open(file, OREAD); + if(text < 0) + fatal(1, "open text '%s'", file); + + Bprint(bioout, "5i\n"); + inithdr(text); + initstk(argc, argv); + + 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.r[REGPC] = fhdr.entry; +} + +void +inithdr(int fd) +{ + Symbol s; + + extern Machdata armmach; + + seek(fd, 0, 0); + if (!crackhdr(fd, &fhdr)) + fatal(0, "read text header"); + + if(fhdr.type != FARM ) + fatal(0, "bad magic number: %d %d", fhdr.type, FARM); + + 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 = &armmach; +} + +void +reset(void) +{ + int i, l, m; + Segment *s; + Breakpoint *b; + + memset(®, 0, sizeof(Registers)); + + 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, tos; + int i; + char *p; + + initmap(); + tos = STACKTOP - sizeof(Tos)*2; /* we'll assume twice the host's is big enough */ + sp = tos; + + /* 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 &= ~7; + reg.r[0] = tos; + reg.r[13] = 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 = "5i: %s\n"; + if(syserr) + s = "5i: %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 %2d %s\n", reg.ar, reg.ir, reg.class, buf); +} + +void +dumpreg(void) +{ + int i; + + Bprint(bioout, "PC #%-8lux SP #%-8lux \n", + reg.r[REGPC], reg.r[REGSP]); + + for(i = 0; i < 16; 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) +{ +} + +void +dumpdreg(void) +{ +} + +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; +} diff --git a/sys/src/cmd/5i/arm.h b/sys/src/cmd/5i/arm.h new file mode 100755 index 000000000..322bcb2be --- /dev/null +++ b/sys/src/cmd/5i/arm.h @@ -0,0 +1,240 @@ +/* + * arm.h + */ +#ifndef EXTERN +#define EXTERN extern +#endif + +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 +{ + Imem, + Iarith, + Ibranch, + Isyscall, +}; + +enum +{ + Nmaxtlb = 64, + REGARG = 0, + REGRET = 0, + REGPC = 15, + REGLINK = 14, + REGSP = 13, +}; + +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 ar; + ulong ir; + Inst* ip; + long r[16]; + long cc1; + long cc2; + int class; + int cond; + int compare_op; + int cbit; + int cout; +}; + +enum +{ + FPd = 0, + FPs, + FPmemory, +}; + +enum +{ + MemRead, + MemReadstring, + MemWrite, +}; + +enum +{ + CCcmp, + CCtst, + CCteq, +}; + +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 Ssyscall(ulong); +int armclass(long); +void breakpoint(char*, char*); +void brkchk(ulong, int); +void cmd(void); +void delbpt(char*); +void dobplist(void); +void dumpdreg(void); +void dumpfreg(void); +void dumpreg(void); +void* emalloc(ulong); +void* erealloc(void*, ulong, ulong); +ulong expr(char*); +void fatal(int, char*, ...); +ulong getmem_2(ulong); +ulong getmem_4(ulong); +uchar getmem_b(ulong); +ushort getmem_h(ulong); +uvlong getmem_v(ulong); +ulong getmem_w(ulong); +ulong ifetch(ulong); +void inithdr(int); +void initicache(void); +void initmap(void); +void initstk(int, char**); +void iprofile(void); +void isum(void); +void itrace(char*, ...); +long lnrand(long); +char* memio(char*, ulong, int, int); +int _mipscoinst(Map*, ulong, char*, int); +Mul mul(long, long); +Mulu mulu(ulong, ulong); +char* nextc(char*); +void printlocals(Symbol*, ulong); +void printparams(Symbol*, ulong); +void printsource(long); +void procinit(int); +void putmem_b(ulong, uchar); +void putmem_h(ulong, ushort); +void putmem_v(ulong, uvlong); +void putmem_w(ulong, ulong); +void reset(void); +void run(void); +void segsum(void); +void stktrace(int); +void tlbsum(void); +void undef(ulong); +void updateicache(ulong addr); +void* vaddr(ulong); + +/* 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; + +/* Plan9 Kernel constants */ +enum +{ + BY2PG = 4096, + BY2WD = 4, + UTZERO = 0x1000, + STACKTOP = 0x80000000, + STACKSIZE = 0x10000, + + PROFGRAN = 4, + Sbit = 1<<20, + SIGNBIT = 0x80000000, + + FP_U = 3, + FP_L = 1, + FP_G = 2, + FP_E = 0, + FP_CBIT = 1<<23, +}; diff --git a/sys/src/cmd/5i/bpt.c b/sys/src/cmd/5i/bpt.c new file mode 100755 index 000000000..2f9362071 --- /dev/null +++ b/sys/src/cmd/5i/bpt.c @@ -0,0 +1,128 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include <ctype.h> +#include "arm.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/5i/cmd.c b/sys/src/cmd/5i/cmd.c new file mode 100755 index 000000000..c27e5adf5 --- /dev/null +++ b/sys/src/cmd/5i/cmd.c @@ -0,0 +1,635 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include <ctype.h> +#include "arm.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.r[15]; + 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': + 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[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[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': + case 'i': + inc = machdata->das(symmap, dot, fmt, str, sizeof(str)); + if(inc < 0) { + Bprint(bioout, "5i: %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) +{ + static int hit = 0; + + hit++; + if(hit > 5) + exits(0); + USED(a); + if(strcmp(msg, "interrupt") != 0) + noted(NDFLT); + + count = 1; + print("5i\n"); + noted(NCONT); +} + +void +setreg(char *addr, char *cp) +{ + int rn; + + dot = expr(addr); + cp = nextc(cp); + if(strcmp(cp, "pc") == 0) { + reg.r[15] = dot; + return; + } + if(strcmp(cp, "sp") == 0) { + reg.r[13] = dot; + return; + } + if(*cp++ == 'r') { + rn = strtoul(cp, 0, 10); + if(rn > 0 && rn < 16) { + 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.r[15]; + 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/5i/float.c b/sys/src/cmd/5i/float.c new file mode 100755 index 000000000..958df2e9f --- /dev/null +++ b/sys/src/cmd/5i/float.c @@ -0,0 +1,203 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include "arm.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 %d\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.r[15]); + longjmp(errjmp, 0); +} + +void +floatop(int dst, int s1, int s2) +{ +} + +void +doubop(int dst, int s1, int s2) +{ +} + +void +Iswc1(ulong inst) +{ +} + +void +Ifsub(ulong ir) +{ +} + +void +Ifmov(ulong ir) +{ +} + +void +Ifabs(ulong ir) +{ +} + +void +Ifneg(ulong ir) +{ +} + +void +Icvtd(ulong ir) +{ +} + +void +Icvts(ulong ir) +{ +} + +void +Icvtw(ulong ir) +{ +} + +void +Ifadd(ulong ir) +{ +} + +void +Ifmul(ulong ir) +{ +} + +void +Ifdiv(ulong ir) +{ +} + +void +Ilwc1(ulong inst) +{ +} + +void +Ibcfbct(ulong inst) +{ +} + +void +Imtct(ulong ir) +{ +} + +void +Imfcf(ulong ir) +{ +} + +void +Icop1(ulong ir) +{ +} + +void +Ifcmp(ulong ir) +{ +} diff --git a/sys/src/cmd/5i/icache.c b/sys/src/cmd/5i/icache.c new file mode 100755 index 000000000..131064126 --- /dev/null +++ b/sys/src/cmd/5i/icache.c @@ -0,0 +1,17 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include "arm.h" + +void +icacheinit(void) +{ +} + +void +updateicache(ulong addr) +{ + USED(addr); +} + diff --git a/sys/src/cmd/5i/mem.c b/sys/src/cmd/5i/mem.c new file mode 100755 index 000000000..5690bd312 --- /dev/null +++ b/sys/src/cmd/5i/mem.c @@ -0,0 +1,285 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include "arm.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[3]<<24 | va[2]<<16 | va[1]<<8 | va[0]; +} + +ulong +getmem_4(ulong addr) +{ + ulong val; + int i; + + val = 0; + for(i = 0; i < 4; i++) + val = (val>>8) | (getmem_b(addr++)<<24); + return val; +} + +ulong +getmem_2(ulong addr) +{ + ulong val; + int i; + + val = 0; + for(i = 0; i < 2; i++) + val = (val>>8) | (getmem_b(addr++)<<16); + return val; +} + +ulong +getmem_w(ulong addr) +{ + uchar *va; + ulong w; + + if(addr&3) { + w = getmem_w(addr & ~3); + while(addr & 3) { + w = (w>>8) | (w<<24); + addr--; + } + return w; + } + if(membpt) + brkchk(addr, Read); + + va = vaddr(addr); + va += addr&(BY2PG-1); + + return va[3]<<24 | va[2]<<16 | va[1]<<8 | va[0]; +} + +ushort +getmem_h(ulong addr) +{ + uchar *va; + ulong w; + + if(addr&1) { + w = getmem_h(addr & ~1); + while(addr & 1) { + w = (w>>8) | (w<<8); + addr--; + } + return w; + } + if(membpt) + brkchk(addr, Read); + + va = vaddr(addr); + va += addr&(BY2PG-1); + + return va[1]<<8 | va[0]; +} + +uchar +getmem_b(ulong addr) +{ + uchar *va; + + if(membpt) + brkchk(addr, Read); + + va = vaddr(addr); + va += addr&(BY2PG-1); + return va[0]; +} + +uvlong +getmem_v(ulong addr) +{ + return ((uvlong)getmem_w(addr+4) << 32) | getmem_w(addr); +} + +void +putmem_h(ulong addr, ushort 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[1] = data>>8; + va[0] = data; + if(membpt) + brkchk(addr, Write); +} + +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[3] = data>>24; + va[2] = data>>16; + va[1] = data>>8; + va[0] = 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_v(ulong addr, uvlong data) +{ + putmem_w(addr, data); /* two stages, to catch brkchk */ + putmem_w(addr+4, data>>32); +} + +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 arm\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 * +vaddr(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; + } + } + } + Bprint(bioout, "User TLB miss vaddr 0x%.8lux\n", addr); + longjmp(errjmp, 0); + return 0; /*to stop compiler whining*/ +} diff --git a/sys/src/cmd/5i/mkfile b/sys/src/cmd/5i/mkfile new file mode 100755 index 000000000..f4060795f --- /dev/null +++ b/sys/src/cmd/5i/mkfile @@ -0,0 +1,26 @@ +</$objtype/mkfile + +TARG=5i +OFILES= 5i.$O\ + run.$O\ + mem.$O\ + syscall.$O\ + stats.$O\ + icache.$O\ + symbols.$O\ + cmd.$O\ + bpt.$O\ + +HFILES=arm.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/5i/run.c b/sys/src/cmd/5i/run.c new file mode 100755 index 000000000..0454ea6de --- /dev/null +++ b/sys/src/cmd/5i/run.c @@ -0,0 +1,948 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include "arm.h" + +static int dummy; +static char* shtype[4] = +{ + "<<", + ">>", + "->", + "@>", +}; +static char* cond[16] = +{ + ".EQ", ".NE", ".HS", ".LO", + ".MI", ".PL", ".VS", ".VC", + ".HI", ".LS", ".GE", ".LT", + ".GT", ".LE", "", ".NO", +}; + +void Idp0(ulong); +void Idp1(ulong); +void Idp2(ulong); +void Idp3(ulong); + +void Imul(ulong); +void Imula(ulong); +void Imull(ulong); + +void Iswap(ulong); +void Imem1(ulong); +void Imem2(ulong); +void Ilsm(ulong inst); + +void Ib(ulong); +void Ibl(ulong); + +void Ssyscall(ulong); + +Inst itab[] = +{ + { Idp0, "AND", Iarith }, /* 00 - r,r,r */ + { Idp0, "EOR", Iarith }, /* 01 */ + { Idp0, "SUB", Iarith }, /* 02 */ + { Idp0, "RSB", Iarith }, /* 03 */ + { Idp0, "ADD", Iarith }, /* 04 */ + { Idp0, "ADC", Iarith }, /* 05 */ + { Idp0, "SBC", Iarith }, /* 06 */ + { Idp0, "RSC", Iarith }, /* 07 */ + { Idp0, "TST", Iarith }, /* 08 */ + { Idp0, "TEQ", Iarith }, /* 09 */ + + { Idp0, "CMP", Iarith }, /* 10 */ + { Idp0, "CMN", Iarith }, /* 11 */ + { Idp0, "ORR", Iarith }, /* 12 */ + { Idp0, "MOV", Iarith }, /* 13 */ + { Idp0, "BIC", Iarith }, /* 14 */ + { Idp0, "MVN", Iarith }, /* 15 */ + { Idp1, "AND", Iarith }, /* 16 */ + { Idp1, "EOR", Iarith }, /* 17 */ + { Idp1, "SUB", Iarith }, /* 18 */ + { Idp1, "RSB", Iarith }, /* 19 */ + + { Idp1, "ADD", Iarith }, /* 20 */ + { Idp1, "ADC", Iarith }, /* 21 */ + { Idp1, "SBC", Iarith }, /* 22 */ + { Idp1, "RSC", Iarith }, /* 23 */ + { Idp1, "TST", Iarith }, /* 24 */ + { Idp1, "TEQ", Iarith }, /* 25 */ + { Idp1, "CMP", Iarith }, /* 26 */ + { Idp1, "CMN", Iarith }, /* 27 */ + { Idp1, "ORR", Iarith }, /* 28 */ + { Idp1, "MOV", Iarith }, /* 29 */ + + { Idp1, "BIC", Iarith }, /* 30 */ + { Idp1, "MVN", Iarith }, /* 31 */ + { Idp2, "AND", Iarith }, /* 32 */ + { Idp2, "EOR", Iarith }, /* 33 */ + { Idp2, "SUB", Iarith }, /* 34 */ + { Idp2, "RSB", Iarith }, /* 35 */ + { Idp2, "ADD", Iarith }, /* 36 */ + { Idp2, "ADC", Iarith }, /* 37 */ + { Idp2, "SBC", Iarith }, /* 38 */ + { Idp2, "RSC", Iarith }, /* 39 */ + + { Idp2, "TST", Iarith }, /* 40 */ + { Idp2, "TEQ", Iarith }, /* 41 */ + { Idp2, "CMP", Iarith }, /* 42 */ + { Idp2, "CMN", Iarith }, /* 43 */ + { Idp2, "ORR", Iarith }, /* 44 */ + { Idp2, "MOV", Iarith }, /* 45 */ + { Idp2, "BIC", Iarith }, /* 46 */ + { Idp2, "MVN", Iarith }, /* 47 */ + { Idp3, "AND", Iarith }, /* 48 - i,r,r */ + { Idp3, "EOR", Iarith }, /* 49 */ + + { Idp3, "SUB", Iarith }, /* 50 */ + { Idp3, "RSB", Iarith }, /* 51 */ + { Idp3, "ADD", Iarith }, /* 52 */ + { Idp3, "ADC", Iarith }, /* 53 */ + { Idp3, "SBC", Iarith }, /* 54 */ + { Idp3, "RSC", Iarith }, /* 55 */ + { Idp3, "TST", Iarith }, /* 56 */ + { Idp3, "TEQ", Iarith }, /* 57 */ + { Idp3, "CMP", Iarith }, /* 58 */ + { Idp3, "CMN", Iarith }, /* 59 */ + + { Idp3, "ORR", Iarith }, /* 60 */ + { Idp3, "MOV", Iarith }, /* 61 */ + { Idp3, "BIC", Iarith }, /* 62 */ + { Idp3, "MVN", Iarith }, /* 63 */ + { Imul, "MUL", Iarith }, /* 64 */ + { Imula, "MULA", Iarith }, /* 65 */ + + { Iswap, "SWPW", Imem }, /* 66 */ + { Iswap, "SWPBU", Imem }, /* 67 */ + + { Imem2, "MOV", Imem }, /* 68 load/store h/sb */ + { Imem2, "MOV", Imem }, /* 69 */ + { Imem2, "MOV", Imem }, /* 70 */ + { Imem2, "MOV", Imem }, /* 71 */ + + { Imem1, "MOVW", Imem }, /* 72 load/store w/ub i,r */ + { Imem1, "MOVB", Imem }, /* 73 */ + { Imem1, "MOVW", Imem }, /* 74 */ + { Imem1, "MOVB", Imem }, /* 75 */ + { Imem1, "MOVW", Imem }, /* 76 load/store r,r */ + { Imem1, "MOVB", Imem }, /* 77 */ + { Imem1, "MOVW", Imem }, /* 78 */ + { Imem1, "MOVB", Imem }, /* 79 */ + + { Ilsm, "LDM", Imem }, /* 80 block move r,r */ + { Ilsm, "STM", Imem }, /* 81 */ + { Ib, "B", Ibranch }, /* 82 branch */ + { Ibl, "BL", Ibranch }, /* 83 */ + { Ssyscall, "SWI", Isyscall }, /* 84 co processor */ + { undef, "undef" }, /* 85 */ + { undef, "undef" }, /* 86 */ + { undef, "undef" }, /* 87 */ + { Imull, "MULLU", Iarith }, /* 88 */ + { Imull, "MULALU", Iarith }, /* 89 */ + { Imull, "MULL", Iarith }, /* 90 */ + { Imull, "MULAL", Iarith }, /* 91 */ + { undef, "undef" }, /* 92 */ + + { 0 } +}; + +int +runcmp(void) +{ + switch(reg.cond) { + case 0x0: /* eq */ return (reg.cc1 == reg.cc2); + case 0x1: /* ne */ return (reg.cc1 != reg.cc2); + case 0x2: /* hs */ return ((ulong)reg.cc1 >= (ulong)reg.cc2); + case 0x3: /* lo */ return ((ulong)reg.cc1 < (ulong)reg.cc2); + case 0x4: /* mi */ return (reg.cc1 - reg.cc2 < 0); + case 0x5: /* pl */ return (reg.cc1 - reg.cc2 >= 0); + case 0x8: /* hi */ return ((ulong)reg.cc1 > (ulong)reg.cc2); + case 0x9: /* ls */ return ((ulong)reg.cc1 <= (ulong)reg.cc2); + case 0xa: /* ge */ return (reg.cc1 >= reg.cc2); + case 0xb: /* lt */ return (reg.cc1 < reg.cc2); + case 0xc: /* gt */ return (reg.cc1 > reg.cc2); + case 0xd: /* le */ return (reg.cc1 <= reg.cc2); + case 0xe: /* al */ return 1; + case 0xf: /* nv */ return 0; + default: + Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n", + reg.cond, reg.cc1, reg.cc2); + undef(reg.ir); + return 0; + } +} + +int +runteq(void) +{ + long res = reg.cc1 ^ reg.cc2; + switch(reg.cond) { + case 0x0: /* eq */ return res == 0; + case 0x1: /* ne */ return res != 0; + case 0x4: /* mi */ return (res & SIGNBIT) != 0; + case 0x5: /* pl */ return (res & SIGNBIT) == 0; + case 0xe: /* al */ return 1; + case 0xf: /* nv */ return 0; + default: + Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n", + reg.cond, reg.cc1, reg.cc2); + undef(reg.ir); + return 0; + } +} + +int +runtst(void) +{ + long res = reg.cc1 & reg.cc2; + switch(reg.cond) { + case 0x0: /* eq */ return res == 0; + case 0x1: /* ne */ return res != 0; + case 0x4: /* mi */ return (res & SIGNBIT) != 0; + case 0x5: /* pl */ return (res & SIGNBIT) == 0; + case 0xe: /* al */ return 1; + case 0xf: /* nv */ return 0; + default: + Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n", + reg.cond, reg.cc1, reg.cc2); + undef(reg.ir); + return 0; + } +} + +void +run(void) +{ + int execute; + + do { + if(trace) + Bflush(bioout); + reg.ar = reg.r[REGPC]; + reg.ir = ifetch(reg.ar); + reg.class = armclass(reg.ir); + reg.ip = &itab[reg.class]; + reg.cond = (reg.ir>>28) & 0xf; + switch(reg.compare_op) { + case CCcmp: + execute = runcmp(); + break; + case CCteq: + execute = runteq(); + break; + case CCtst: + execute = runtst(); + break; + default: + Bprint(bioout, "unimplemented compare operation %x\n", + reg.compare_op); + return; + } + + if(execute) { + reg.ip->count++; + (*reg.ip->func)(reg.ir); + } else { + if(trace) + itrace("%s%s IGNORED", + reg.ip->name, cond[reg.cond]); + } + reg.r[REGPC] += 4; + if(bplist) + brkchk(reg.r[REGPC], Instruction); + } while(--count); +} + +void +undef(ulong inst) +{ + Bprint(bioout, "undefined instruction trap pc #%lux inst %.8lux class %d\n", + reg.r[REGPC], inst, reg.class); + longjmp(errjmp, 0); +} + +long +shift(long v, int st, int sc, int isreg) +{ + if(sc == 0) { + switch(st) { + case 0: /* logical left */ + reg.cout = reg.cbit; + break; + case 1: /* logical right */ + reg.cout = (v >> 31) & 1; + break; + case 2: /* arith right */ + reg.cout = reg.cbit; + break; + case 3: /* rotate right */ + if(isreg) { + reg.cout = reg.cbit; + } + else { + reg.cout = v & 1; + v = ((ulong)v >> 1) | (reg.cbit << 31); + } + } + } + else { + switch(st) { + case 0: /* logical left */ + reg.cout = (v >> (32 - sc)) & 1; + v = v << sc; + break; + case 1: /* logical right */ + reg.cout = (v >> (sc - 1)) & 1; + v = (ulong)v >> sc; + break; + case 2: /* arith right */ + if(sc >= 32) { + reg.cout = (v >> 31) & 1; + if(reg.cout) + v = 0xFFFFFFFF; + else + v = 0; + } + else { + reg.cout = (v >> (sc - 1)) & 1; + v = (long)v >> sc; + } + break; + case 3: /* rotate right */ + reg.cout = (v >> (sc - 1)) & 1; + v = (v << (32-sc)) | ((ulong)v >> sc); + break; + } + } + return v; +} + +void +dpex(long inst, long o1, long o2, int rd) +{ + int cbit; + + cbit = 0; + switch((inst>>21) & 0xf) { + case 0: /* and */ + reg.r[rd] = o1 & o2; + cbit = 1; + break; + case 1: /* eor */ + reg.r[rd] = o1 ^ o2; + cbit = 1; + break; + case 2: /* sub */ + reg.r[rd] = o1 - o2; + case 10: /* cmp */ + if(inst & Sbit) { + reg.cc1 = o1; + reg.cc2 = o2; + reg.compare_op = CCcmp; + } + return; + case 3: /* rsb */ + reg.r[rd] = o2 - o1; + if(inst & Sbit) { + reg.cc1 = o2; + reg.cc2 = o1; + reg.compare_op = CCcmp; + } + return; + case 4: /* add */ + if(calltree && rd == REGPC && o2 == 0) { + Symbol s; + + findsym(o1 + o2, CTEXT, &s); + Bprint(bioout, "%8lux return to %lux %s r0=%lux\n", + reg.r[REGPC], o1 + o2, s.name, reg.r[REGRET]); + } + reg.r[rd] = o1 + o2; + if(inst & Sbit) { + if(((uvlong)(ulong)o1 + (uvlong)(ulong)o2) & (1LL << 32)) + reg.cbit = 1; + else + reg.cbit = 0; + reg.cc1 = o2; + reg.cc2 = -o1; + reg.compare_op = CCcmp; + } + return; + case 5: /* adc */ + case 6: /* sbc */ + case 7: /* rsc */ + undef(inst); + case 8: /* tst */ + if(inst & Sbit) { + reg.cc1 = o1; + reg.cc2 = o2; + reg.compare_op = CCtst; + } + return; + case 9: /* teq */ + if(inst & Sbit) { + reg.cc1 = o1; + reg.cc2 = o2; + reg.compare_op = CCteq; + } + return; + case 11: /* cmn */ + if(inst & Sbit) { + reg.cc1 = o1; + reg.cc2 = -o2; + reg.compare_op = CCcmp; + } + return; + case 12: /* orr */ + reg.r[rd] = o1 | o2; + cbit = 1; + break; + case 13: /* mov */ + reg.r[rd] = o2; + cbit = 1; + break; + case 14: /* bic */ + reg.r[rd] = o1 & ~o2; + cbit = 1; + break; + case 15: /* mvn */ + reg.r[rd] = ~o2; + cbit = 1; + break; + } + if(inst & Sbit) { + if(cbit) + reg.cbit = reg.cout; + reg.cc1 = reg.r[rd]; + reg.cc2 = 0; + reg.compare_op = CCcmp; + } +} + +/* + * data processing instruction R,R,R + */ +void +Idp0(ulong inst) +{ + int rn, rd, rm; + long o1, o2; + + rn = (inst>>16) & 0xf; + rd = (inst>>12) & 0xf; + rm = inst & 0xf; + o1 = reg.r[rn]; + if(rn == REGPC) + o1 += 8; + o2 = reg.r[rm]; + if(rm == REGPC) + o2 += 8; + + dpex(inst, o1, o2, rd); + if(trace) + itrace("%s%s\tR%d,R%d,R%d =#%x", + reg.ip->name, cond[reg.cond], + rm, rn, rd, + reg.r[rd]); + if(rd == REGPC) + reg.r[rd] -= 4; +} + +/* + * data processing instruction (R<>#),R,R + */ +void +Idp1(ulong inst) +{ + int rn, rd, rm, st, sc; + long o1, o2; + + rn = (inst>>16) & 0xf; + rd = (inst>>12) & 0xf; + rm = inst & 0xf; + st = (inst>>5) & 0x3; + sc = (inst>>7) & 0x1f; + o1 = reg.r[rn]; + if(rn == REGPC) + o1 += 8; + o2 = reg.r[rm]; + if(rm == REGPC) + o2 += 8; + o2 = shift(o2, st, sc, 0); + dpex(inst, o1, o2, rd); + if(trace) + itrace("%s%s\tR%d%s%d,R%d,R%d =#%x", + reg.ip->name, cond[reg.cond], rm, shtype[st], sc, rn, rd, + reg.r[rd]); + if(rd == REGPC) + reg.r[rd] -= 4; +} + +/* + * data processing instruction (R<>R),R,R + */ +void +Idp2(ulong inst) +{ + int rn, rd, rm, rs, st; + long o1, o2, o3; + + rn = (inst>>16) & 0xf; + rd = (inst>>12) & 0xf; + rm = inst & 0xf; + st = (inst>>5) & 0x3; + rs = (inst>>8) & 0xf; + o1 = reg.r[rn]; + if(rn == REGPC) + o1 += 8; + o2 = reg.r[rm]; + if(rm == REGPC) + o2 += 8; + o3 = reg.r[rs]; + if(rs == REGPC) + o3 += 8; + o2 = shift(o2, st, o3, 1); + dpex(inst, o1, o2, rd); + if(trace) + itrace("%s%s\tR%d%sR%d=%d,R%d,R%d =#%x", + reg.ip->name, cond[reg.cond], rm, shtype[st], rs, o3, rn, rd, + reg.r[rd]); + if(rd == REGPC) + reg.r[rd] -= 4; +} + +/* + * data processing instruction #<>#,R,R + */ +void +Idp3(ulong inst) +{ + int rn, rd, sc; + long o1, o2; + + rn = (inst>>16) & 0xf; + rd = (inst>>12) & 0xf; + o1 = reg.r[rn]; + if(rn == REGPC) + o1 += 8; + o2 = inst & 0xff; + sc = (inst>>7) & 0x1e; + o2 = (o2 >> sc) | (o2 << (32 - sc)); + + dpex(inst, o1, o2, rd); + if(trace) + itrace("%s%s\t#%x,R%d,R%d =#%x", + reg.ip->name, cond[reg.cond], o2, rn, rd, + reg.r[rd]); + if(rd == REGPC) + reg.r[rd] -= 4; +} + +void +Imul(ulong inst) +{ + int rs, rd, rm; + + rd = (inst>>16) & 0xf; + rs = (inst>>8) & 0xf; + rm = inst & 0xf; + + if(rd == REGPC || rs == REGPC || rm == REGPC || rd == rm) + undef(inst); + + reg.r[rd] = reg.r[rm]*reg.r[rs]; + + if(trace) + itrace("%s%s\tR%d,R%d,R%d =#%x", + reg.ip->name, cond[reg.cond], rs, rm, rd, + reg.r[rd]); +} + +void +Imull(ulong inst) +{ + vlong v; + int rs, rd, rm, rn; + + rd = (inst>>16) & 0xf; + rn = (inst>>12) & 0xf; + rs = (inst>>8) & 0xf; + rm = inst & 0xf; + + if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC + || rd == rm || rn == rm || rd == rn) + undef(inst); + + if(inst & (1<<22)){ + v = (vlong)reg.r[rm] * (vlong)reg.r[rs]; + if(inst & (1 << 21)) + v += reg.r[rn]; + }else{ + v = (uvlong)(ulong)reg.r[rm] * (uvlong)(ulong)reg.r[rs]; + if(inst & (1 << 21)) + v += (ulong)reg.r[rn]; + } + reg.r[rd] = v >> 32; + reg.r[rn] = v; + + if(trace) + itrace("%s%s\tR%d,R%d,(R%d,R%d) =#%llx", + reg.ip->name, cond[reg.cond], rs, rm, rn, rd, + v); +} + +void +Imula(ulong inst) +{ + int rs, rd, rm, rn; + + rd = (inst>>16) & 0xf; + rn = (inst>>12) & 0xf; + rs = (inst>>8) & 0xf; + rm = inst & 0xf; + + if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC || rd == rm) + undef(inst); + + reg.r[rd] = reg.r[rm]*reg.r[rs] + reg.r[rn]; + + if(trace) + itrace("%s%s\tR%d,R%d,R%d,R%d =#%x", + reg.ip->name, cond[reg.cond], rs, rm, rn, rd, + reg.r[rd]); +} + +void +Iswap(ulong inst) +{ + int rn, rd, rm; + ulong address, value, bbit; + + bbit = inst & (1<<22); + rn = (inst>>16) & 0xf; + rd = (inst>>12) & 0xf; + rm = (inst>>0) & 0xf; + + address = reg.r[rn]; + if(bbit) { + value = getmem_b(address); + putmem_b(address, reg.r[rm]); + } else { + value = getmem_w(address); + putmem_w(address, reg.r[rm]); + } + reg.r[rd] = value; + + if(trace) { + char *bw, *dotc; + + bw = ""; + if(bbit) + bw = "B"; + dotc = cond[reg.cond]; + + itrace("SWP%s%s\t#%x(R%d),R%d #%lux=#%x", + bw, dotc, + rn, rd, + address, value); + } +} + +/* + * load/store word/byte + */ +void +Imem1(ulong inst) +{ + int rn, rd, off, rm, sc, st; + ulong address, value, pbit, ubit, bbit, wbit, lbit, bit25; + + bit25 = inst & (1<<25); + pbit = inst & (1<<24); + ubit = inst & (1<<23); + bbit = inst & (1<<22); + wbit = inst & (1<<21); + lbit = inst & (1<<20); + rn = (inst>>16) & 0xf; + rd = (inst>>12) & 0xf; + + SET(st); + SET(sc); + SET(rm); + if(bit25) { + rm = inst & 0xf; + st = (inst>>5) & 0x3; + sc = (inst>>7) & 0x1f; + off = reg.r[rm]; + if(rm == REGPC) + off += 8; + off = shift(off, st, sc, 0); + } else { + off = inst & 0xfff; + } + if(!ubit) + off = -off; + if(rn == REGPC) + off += 8; + + address = reg.r[rn]; + if(pbit) + address += off; + + if(lbit) { + if(bbit) + value = getmem_b(address); + else + value = getmem_w(address); + if(rd == REGPC) + value -= 4; + reg.r[rd] = value; + } else { + value = reg.r[rd]; + if(rd == REGPC) + value -= 4; + if(bbit) + putmem_b(address, value); + else + putmem_w(address, value); + } + if(!(pbit && !wbit)) + reg.r[rn] += off; + + if(trace) { + char *bw, *dotp, *dotc; + + bw = "W"; + if(bbit) + bw = "BU"; + dotp = ""; + if(!pbit) + dotp = ".P"; + dotc = cond[reg.cond]; + + if(lbit) { + if(!bit25) + itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x", + bw, dotp, dotc, + off, rn, rd, + address, value); + else + itrace("MOV%s%s%s\t(R%d%s%d)(R%d),R%d #%lux=#%x", + bw, dotp, dotc, + rm, shtype[st], sc, rn, rd, + address, value); + } else { + if(!bit25) + itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x", + bw, dotp, dotc, + rd, off, rn, + address, value); + else + itrace("MOV%s%s%s\tR%d,(R%d%s%d)(R%d) #%lux=#%x", + bw, dotp, dotc, + rd, rm, shtype[st], sc, rn, + address, value); + } + } +} + +/* + * load/store unsigned byte/half word + */ +void +Imem2(ulong inst) +{ + int rn, rd, off, rm; + ulong address, value, pbit, ubit, hbit, sbit, wbit, lbit, bit22; + + pbit = inst & (1<<24); + ubit = inst & (1<<23); + bit22 = inst & (1<<22); + wbit = inst & (1<<21); + lbit = inst & (1<<20); + sbit = inst & (1<<6); + hbit = inst & (1<<5); + rn = (inst>>16) & 0xf; + rd = (inst>>12) & 0xf; + + SET(rm); + if(bit22) { + off = ((inst>>4) & 0xf0) | (inst & 0xf); + } else { + rm = inst & 0xf; + off = reg.r[rm]; + if(rm == REGPC) + off += 8; + } + if(!ubit) + off = -off; + if(rn == REGPC) + off += 8; + + address = reg.r[rn]; + if(pbit) + address += off; + + if(lbit) { + if(hbit) { + value = getmem_h(address); + if(sbit && (value & 0x8000)) + value |= 0xffff0000; + } else { + value = getmem_b(address); + if(value & 0x80) + value |= 0xffffff00; + } + if(rd == REGPC) + value -= 4; + reg.r[rd] = value; + } else { + value = reg.r[rd]; + if(rd == REGPC) + value -= 4; + if(hbit) { + putmem_h(address, value); + } else { + putmem_b(address, value); + } + } + if(!(pbit && !wbit)) + reg.r[rn] += off; + + if(trace) { + char *hb, *dotp, *dotc; + + hb = "B"; + if(hbit) + hb = "H"; + dotp = ""; + if(!pbit) + dotp = ".P"; + dotc = cond[reg.cond]; + + if(lbit) { + if(bit22) + itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x", + hb, dotp, dotc, + off, rn, rd, + address, value); + else + itrace("MOV%s%s%s\t(R%d)(R%d),R%d #%lux=#%x", + hb, dotp, dotc, + rm, rn, rd, + address, value); + } else { + if(bit22) + itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x", + hb, dotp, dotc, + rd, off, rn, + address, value); + else + itrace("MOV%s%s%s\tR%d,(R%d)(R%d) #%lux=#%x", + hb, dotp, dotc, + rd, rm, rn, + address, value); + } + } +} + +void +Ilsm(ulong inst) +{ + char pbit, ubit, sbit, wbit, lbit; + int i, rn, reglist; + ulong address, predelta, postdelta; + + pbit = (inst>>24) & 0x1; + ubit = (inst>>23) & 0x1; + sbit = (inst>>22) & 0x1; + wbit = (inst>>21) & 0x1; + lbit = (inst>>20) & 0x1; + rn = (inst>>16) & 0xf; + reglist = inst & 0xffff; + + if(reglist & 0x8000) + undef(reg.ir); + if(sbit) + undef(reg.ir); + + address = reg.r[rn]; + + if(pbit) { + predelta = 4; + postdelta = 0; + } else { + predelta = 0; + postdelta = 4; + } + if(ubit) { + for (i = 0; i < 16; ++i) { + if(!(reglist & (1 << i))) + continue; + address += predelta; + if(lbit) + reg.r[i] = getmem_w(address); + else + putmem_w(address, reg.r[i]); + address += postdelta; + } + } else { + for (i = 15; 0 <= i; --i) { + if(!(reglist & (1 << i))) + continue; + address -= predelta; + if(lbit) + reg.r[i] = getmem_w(address); + else + putmem_w(address, reg.r[i]); + address -= postdelta; + } + } + if(wbit) { + reg.r[rn] = address; + } + + if(trace) { + itrace("%s.%c%c\tR%d=%lux%s, <%lux>", + (lbit ? "LDM" : "STM"), (ubit ? 'I' : 'D'), (pbit ? 'B' : 'A'), + rn, reg.r[rn], (wbit ? "!" : ""), reglist); + } +} + +void +Ib(ulong inst) +{ + long v; + + v = inst & 0xffffff; + v = reg.r[REGPC] + 8 + ((v << 8) >> 6); + if(trace) + itrace("B%s\t#%lux", cond[reg.cond], v); + reg.r[REGPC] = v - 4; +} + +void +Ibl(ulong inst) +{ + long v; + Symbol s; + + v = inst & 0xffffff; + v = reg.r[REGPC] + 8 + ((v << 8) >> 6); + if(trace) + itrace("BL%s\t#%lux", cond[reg.cond], v); + + if(calltree) { + findsym(v, CTEXT, &s); + Bprint(bioout, "%8lux %s(", reg.r[REGPC], s.name); + printparams(&s, reg.r[13]); + Bprint(bioout, "from "); + printsource(reg.r[REGPC]); + Bputc(bioout, '\n'); + } + + reg.r[REGLINK] = reg.r[REGPC] + 4; + reg.r[REGPC] = v - 4; +} diff --git a/sys/src/cmd/5i/stats.c b/sys/src/cmd/5i/stats.c new file mode 100755 index 000000000..65485533d --- /dev/null +++ b/sys/src/cmd/5i/stats.c @@ -0,0 +1,199 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include "arm.h" + +#define Percent(num, max) ((max)?((num)*100)/(max):0) +#define prof prof5i + +extern Inst itab[]; +Inst *tables[] = { itab, 0 }; + +void +isum(void) +{ + Inst *i; + int total, mems, arith, branch; + int useddelay, taken, syscall; + int pct, j; + + total = 0; + mems = 0; + arith = 0; + branch = 0; + useddelay = 0; + taken = 0; + syscall = 0; + + /* Compute the total so we can have percentages */ + for(i = itab; 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) { + /* This is gross */ + 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 Imem: + mems += i->count; + break; + case Iarith: + arith += i->count; + break; + case Ibranch: + branch += i->count; + taken += i->taken; + useddelay += i->useddelay; + break; + case Isyscall: + syscall += i->count; + break; + } + + } + } + } + + Bprint(bioout, "\n%-8ud Memory cycles\n", mems+total); + Bprint(bioout, "%-8ud %3d%% Instruction cycles\n", + total, Percent(total, mems+total)); + Bprint(bioout, "%-8ud %3d%% Data cycles\n\n", + mems, Percent(mems, mems+total)); + + Bprint(bioout, "%-8ud %3d%% Arithmetic\n", + arith, Percent(arith, 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/5i/symbols.c b/sys/src/cmd/5i/symbols.c new file mode 100755 index 000000000..9accb9d1e --- /dev/null +++ b/sys/src/cmd/5i/symbols.c @@ -0,0 +1,95 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#include "arm.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.r[15]; + sp = reg.r[13]; + 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[14]; + 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/5i/syscall.c b/sys/src/cmd/5i/syscall.c new file mode 100755 index 000000000..b6402bfd5 --- /dev/null +++ b/sys/src/cmd/5i/syscall.c @@ -0,0 +1,807 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define EXTERN +#include "arm.h" + +#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] "Running", + [_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[1]]); + exits(0); +} + +void +sys_errstr(void) +{ + ulong str; + + str = getmem_w(reg.r[13]+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; + int n; + + str = getmem_w(reg.r[13]+4); + n = getmem_w(reg.r[13]+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 +sysbind(void) +{ + ulong pname, pold, flags; + char name[1024], old[1024]; + int n; + + pname = getmem_w(reg.r[13]+4); + pold = getmem_w(reg.r[13]+8); + flags = getmem_w(reg.r[13]+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 +sysfd2path(void) +{ + int n; + uint fd; + ulong str; + char buf[1024]; + + fd = getmem_w(reg.r[13]+4); + str = getmem_w(reg.r[13]+8); + n = getmem_w(reg.r[13]+12); + if(sysdbg) + itrace("fd2path(0x%lux, 0x%lux, 0x%lux)", fd, str, n); + reg.r[1] = -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 +syschdir(void) +{ + char file[1024]; + int n; + ulong name; + + name = getmem_w(reg.r[13]+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[13]+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[13]+4); + newfd = getmem_w(reg.r[13]+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[13]+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[13]+4); + mode = getmem_w(reg.r[13]+8); + memio(file, name, sizeof(file), MemReadstring); + + n = open(file, mode); + if(n < 0) + errstr(errbuf, sizeof errbuf); + + if(sysdbg) + itrace("open(0x%lux='%s', 0x%lux) = %d", name, file, mode, n); + + 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[13]+4); + a = getmem_w(reg.r[13]+8); + size = getmem_w(reg.r[13]+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) +{ + sysread(getmem_v(reg.r[13]+16)); +} + +void +sysseek(void) +{ + int fd; + ulong mode; + ulong retp; + vlong v; + + retp = getmem_w(reg.r[13]+4); + fd = getmem_w(reg.r[13]+8); + v = getmem_v(reg.r[13]+16); + mode = getmem_w(reg.r[13]+20); + if(sysdbg) + itrace("seek(%d, %lld, %d)", fd, v, mode); + + v = seek(fd, v, mode); + if(v < 0) + errstr(errbuf, sizeof errbuf); + + putmem_v(retp, v); +} + +void +sysoseek(void) +{ + int fd, n; + ulong off, mode; + + fd = getmem_w(reg.r[13]+4); + off = getmem_w(reg.r[13]+8); + mode = getmem_w(reg.r[13]+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 +syssleep(void) +{ + ulong len; + int n; + + len = getmem_w(reg.r[13]+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[13]+4); + edir = getmem_w(reg.r[13]+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[13]+4); + edir = getmem_w(reg.r[13]+8); + n = getmem_w(reg.r[13]+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]; + extern int _fstat(int, char*); /* old system call */ + ulong edir; + int n, fd; + + fd = getmem_w(reg.r[13]+4); + edir = getmem_w(reg.r[13]+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[13]+4); + edir = getmem_w(reg.r[13]+8); + n = getmem_w(reg.r[13]+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[13]+4); + a = getmem_w(reg.r[13]+8); + size = getmem_w(reg.r[13]+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, 0x%llx) = %d", fd, a, size, offset, n); + + free(buf); + + reg.r[REGRET] = n; +} + +void +sys_write(void) +{ + syswrite(-1LL); +} + +void +syspwrite(void) +{ + syswrite(getmem_v(reg.r[13]+16)); +} + +void +syspipe(void) +{ + int n, p[2]; + ulong fd; + + fd = getmem_w(reg.r[13]+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[13]+4); + mode = getmem_w(reg.r[13]+8); + perm = getmem_w(reg.r[13]+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[13]+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[13]+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[13]+4); + if(sysdbg) + itrace("notify(0x%lux)\n", nofunc); + + reg.r[REGRET] = 0; +} + +void +sys_wait(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysawait(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysrfork(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +syswstat(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sys_wstat(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysfwstat(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sys_fwstat(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysnoted(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +syssegattach(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +syssegdetach(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +syssegfree(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +syssegflush(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysrendezvous(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysunmount(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysfork(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysforkpgrp(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +syssegbrk(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysmount(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysalarm(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysexec(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sys_fsession(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysfauth(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + exits(0); +} +void +sysfversion(void) +{ + Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]); + 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 +Ssyscall(ulong) +{ + int call; + + call = reg.r[REGARG]; + if(call < 0 || call >= nelem(systab) || systab[call] == nil) { + Bprint(bioout, "bad system call %d (%#ux)\n", call, call); + dumpreg(); + Bflush(bioout); + return; + } + + if(trace) + itrace("SWI\t%s", sysctab[call]); + (*systab[call])(); + Bflush(bioout); +} |