Commit Diff


commit - a5f9ff62b2d70a5b75efe8e4f993aec10f209095
commit + 4f2ac1b76b04df503944e86c2e7f152c2ff53f0e
blob - 597bf58c88c2d034b31e770816d39cae76c82810
blob + 90cfc2a5c1e3cf75d632b940a809ffdb3703f612
--- src/cmd/acid/Notes
+++ src/cmd/acid/Notes
@@ -20,6 +20,8 @@ map() returns 5-tuples: (name, filename, base, end, of
 
 map() expects a 5-tuple too
 
+new acid maps() prints maps nicely.
+
 strace expects a list of register names and values like
 	{"PC", *PC, "SP", *SP}
 
@@ -41,6 +43,34 @@ new builtin deltextfile(file) removes a file from the 
 
 both textfile and deltextfile update symbols.
 
+new types: register is something that when dereferenced gives you
+	the registers.  the Ureg is no longer mapped at 0.
+	refconst is something that gives a constant when dereferenced.
+
+new builtin register("AX") creates register values
+new builtin refconst(0x123) creates refconst values
+
+new builtin var("foo") is equivalent to the variable foo
+	(it returns foo but can also be used as the lhs of an assignment).
+
+new acid function getregs() returns a list of the current values of registers.
+new acid function setregs() sets the current registers to those values.
+	note that getregs and setregs operate on register locations, not the
+		register values themselves.  
+new acid function resetregs() sets registers to register("AX"), etc.
+new acid function clearregs() sets all registers to constant -1.
+
+the default register settings are as in resetregs(), not small numbers.
+the Ureg is not mapped at 0 anymore.
+
+new acid variables coretext, pids, systype, corefile, cmdline.
+
+new behavior: local variable lookup, stk, etc., use the acid values of registers
+	(*PC, *SP, and so on), so the thread support code can change the context
+	completely.
+
+unary + is applicable to more data types and prints more often.
+
 ====
 
 yet to be done:
blob - 44718009ef5d0c1136b0442bdf5d6d96f584e034
blob + 866816e8985498829cdf845b3567d18ab33314d0
--- src/cmd/acid/acid.h
+++ src/cmd/acid/acid.h
@@ -44,6 +44,7 @@ Extern int	interactive;
 Extern Node*	code;
 Extern int	na;
 Extern int	wtflag;
+Extern Regs*	acidregs;
 Extern Regs*	correg;
 Extern Map*	cormap;
 Extern Map*	symmap;
@@ -76,6 +77,8 @@ enum
 	TSTRING,
 	TLIST,
 	TCODE,
+	TREG,
+	TCON,
 	NUMT,
 };
 
@@ -129,6 +132,8 @@ struct Store
 		String*	string;
 		List*	l;
 		Node*	cc;
+		char*	reg;
+		Node*	con;
 	} u;
 };
 
@@ -182,6 +187,7 @@ struct String
 	int	len;
 };
 
+int	acidregsrw(Regs*, char*, ulong*, int);
 List*	addlist(List*, List*);
 void	addvarsym(Fhdr*);
 List*	al(int);
@@ -212,6 +218,7 @@ void	gc(void);
 char*	getstatus(int);
 void*	gmalloc(long);
 void	indir(Map*, ulong, char, Node*);
+void	indirreg(Regs*, char*, char, Node*);
 void	initexpr(void);
 void	initprint(void);
 void	installbuiltin(void);
@@ -257,7 +264,8 @@ void	userinit(void);
 void	varreg(void);
 void	varsym(void);
 void	whatis(Lsym*);
-void	windir(Map*, Node*, Node*, Node*);
+void	windir(Map*, Node, Node*, Node*);
+void	windirreg(Regs*, char*, Node*, Node*);
 void	yyerror(char*, ...);
 int	yylex(void);
 int	yyparse(void);
@@ -313,5 +321,6 @@ enum
 	OFMT,
 	OEVAL,
 	OWHAT,
+	OUPLUS,
 	NUMO,
 };
blob - 490c4521e34522c97e6aacb937f307ec1f03f9f0
blob + 316c49211f429a337243154fdbe8a03e3a5f2aff
--- src/cmd/acid/builtin.c
+++ src/cmd/acid/builtin.c
@@ -44,6 +44,9 @@ void	regexp(Node*, Node*);
 void textfile(Node*, Node*);
 void deltextfile(Node*, Node*);
 void stringn(Node*, Node*);
+void xregister(Node*, Node*);
+void refconst(Node*, Node*);
+void dolook(Node*, Node*);
 
 typedef struct Btab Btab;
 struct Btab
@@ -52,13 +55,12 @@ struct Btab
 	void	(*fn)(Node*, Node*);
 } tab[] =
 {
+	"access",	doaccess,
 	"atof",		cvtatof,
 	"atoi",		cvtatoi,
 	"deltextfile",	deltextfile,
 	"error",	doerror,
 	"file",		getfile,
-	"readfile",	readfile,
-	"access",	doaccess,
 	"filepc",	filepc,
 	"fnbound",	funcbound,
 	"fmt",		fmt,
@@ -76,8 +78,11 @@ struct Btab
 	"print",	bprint,
 	"printto",	printto,
 	"rc",		rc,
+	"readfile",	readfile,
 	"reason",	reason,
+	"refconst",	refconst,
 	"regexp",	regexp,
+	"register",	xregister,
 	"setproc",	setproc,
 	"start",	start,
 	"startstop",	startstop,
@@ -87,6 +92,7 @@ struct Btab
 	"stringn",	stringn,
 	"sysstop",		sysstop,
 	"textfile",	textfile,
+	"var",	dolook,
 	"waitstop",	waitstop,
 	0
 };
@@ -317,6 +323,65 @@ xkill(Node *r, Node *args)
 }
 
 void
+xregister(Node *r, Node *args)
+{
+	Regdesc *rp;
+	Node res;
+
+	if(args == 0)
+		error("register(string): arg count");
+	expr(args, &res);
+	if(res.type != TSTRING)
+		error("register(string): arg type");
+
+	if((rp = regdesc(res.store.u.string->string)) == nil)
+		error("no such register");
+
+	r->op = OCONST;
+	r->type = TREG;
+	r->store.fmt = rp->format;
+	r->store.u.reg = rp->name;
+}
+
+void
+refconst(Node *r, Node *args)
+{
+	Node *n;
+
+	if(args == 0)
+		error("refconst(expr): arg count");
+
+	n = an(OCONST, ZN, ZN);
+	expr(args, n);
+
+	r->op = OCONST;
+	r->type = TCON;
+	r->store.u.con = n;
+}
+
+void
+dolook(Node *r, Node *args)
+{
+	Node res;
+	Lsym *l;
+
+	if(args == 0)
+		error("var(string): arg count");
+	expr(args, &res);
+	if(res.type != TSTRING)
+		error("var(string): arg type");
+
+	r->op = OCONST;
+	if((l = look(res.store.u.string->string)) == nil || l->v->set == 0){
+		r->type = TLIST;
+		r->store.u.l = nil;
+	}else{
+		r->type = l->v->type;
+		r->store = l->v->store;
+	}
+}
+
+void
 status(Node *r, Node *args)
 {
 	Node res;
@@ -350,7 +415,7 @@ reason(Node *r, Node *args)
 	r->op = OCONST;
 	r->type = TSTRING;
 	r->store.fmt = 's';
-	r->store.u.string = strnode((*mach->exc)(cormap, correg));
+	r->store.u.string = strnode((*mach->exc)(cormap, acidregs));
 }
 
 void
@@ -367,7 +432,7 @@ follow(Node *r, Node *args)
 	if(res.type != TINT)
 		error("follow(addr): arg type");
 
-	n = (*mach->foll)(cormap, correg, res.store.u.ival, f);
+	n = (*mach->foll)(cormap, acidregs, res.store.u.ival, f);
 	if (n < 0)
 		error("follow(addr): %r");
 	tail = &r->store.u.l;
@@ -953,7 +1018,7 @@ straceregrw(Regs *regs, char *name, ulong *val, int is
 			*val = sregs[i].val;
 			return 0;
 		}
-	return rget(correg, name, val);
+	return rget(acidregs, name, val);
 }
 
 void
@@ -1058,6 +1123,65 @@ patom(char type, Store *res)
 	int i;
 	char buf[512];
 	extern char *typenames[];
+	Node *n;
+
+	switch(type){
+	case TREG:
+		Bprint(bout, "register(\"%s\")", res->u.reg);
+		return;
+	case TCON:
+		Bprint(bout, "refconst(");
+		n = res->u.con;
+		patom(n->type, &n->store);
+		Bprint(bout, ")");
+		return;
+	}
+
+	switch(res->fmt){
+	case 'c':
+	case 'C':
+	case 'r':
+	case 'B':
+	case 'b':
+	case 'X':
+	case 'x':
+	case 'W':
+	case 'D':
+	case 'd':
+	case 'u':
+	case 'U':
+	case 'Z':
+	case 'V':
+	case 'Y':
+	case 'o':
+	case 'O':
+	case 'q':
+	case 'Q':
+	case 'a':
+	case 'A':
+	case 'I':
+	case 'i':
+		if(type != TINT){
+		badtype:
+			Bprint(bout, "*%s\\%c*", typenames[(uchar)type], res->fmt);
+			return;
+		}
+		break;
+
+	case 'f':
+	case 'F':
+		if(type != TFLOAT)
+			goto badtype;
+		break;
+
+	case 's':
+	case 'g':
+	case 'G':
+	case 'R':
+		if(type != TSTRING)
+			goto badtype;
+		break;
+	}
 
 	switch(res->fmt) {
 	case 'c':
@@ -1129,24 +1253,15 @@ patom(char type, Store *res)
 		break;
 	case 'f':
 	case 'F':
-		if(type != TFLOAT)
-			Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
-		else
-			Bprint(bout, "%g", res->u.fval);
+		Bprint(bout, "%g", res->u.fval);
 		break;
 	case 's':
 	case 'g':
 	case 'G':
-		if(type != TSTRING)
-			Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
-		else
-			Bwrite(bout, res->u.string->string, res->u.string->len);
+		Bwrite(bout, res->u.string->string, res->u.string->len);
 		break;
 	case 'R':
-		if(type != TSTRING)
-			Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
-		else
-			Bprint(bout, "%S", (Rune*)res->u.string->string);
+		Bprint(bout, "%S", (Rune*)res->u.string->string);
 		break;
 	case 'a':
 	case 'A':
@@ -1155,14 +1270,10 @@ patom(char type, Store *res)
 		break;
 	case 'I':
 	case 'i':
-		if(type != TINT)
-			Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
-		else {
-			if (symmap == nil || (*mach->das)(symmap, res->u.ival, res->fmt, buf, sizeof(buf)) < 0)
-				Bprint(bout, "no instruction");
-			else
-				Bprint(bout, "%s", buf);
-		}
+		if (symmap == nil || (*mach->das)(symmap, res->u.ival, res->fmt, buf, sizeof(buf)) < 0)
+			Bprint(bout, "no instruction");
+		else
+			Bprint(bout, "%s", buf);
 		break;
 	}
 }
@@ -1406,6 +1517,7 @@ textfile(Node *r, Node *args)
 			unmapfile(corhdr, cormap);
 			mapfile(fp, base, cormap, nil);
 			free(correg);
+			correg = nil;
 			mapfile(corhdr, 0, cormap, &correg);
 		}
 		if(symopen(fp) < 0)
@@ -1476,8 +1588,6 @@ deltextfile(Node *r, Node *args)
 		error("symbol file %s not open", file);
 }
 
-int xget1(Map *m, ulong addr, u8int *a, int n);
-
 void
 stringn(Node *r, Node *args)
 {
@@ -1507,7 +1617,7 @@ stringn(Node *r, Node *args)
 
 	r->type = TSTRING;
 	for(i=0; i<n; i++){
-		ret = xget1(cormap, addr, (uchar*)&buf[i], 1);
+		ret = get1(cormap, addr, (uchar*)&buf[i], 1);
 		if(ret < 0){
 			free(buf);
 			error("indir: %r");
blob - afdf538c1462f79d2953268769c593067f309613
blob + 3d1886c7a1c85270248848599b8c3e3104754583
--- src/cmd/acid/dbg.y
+++ src/cmd/acid/dbg.y
@@ -282,8 +282,7 @@ monexpr		: term
 		}
 		| '+' monexpr
 		{
-			$$ = con(0);
-			$$ = an(OADD, $2, $$);
+			$$ = an(OUPLUS, $2, ZN);
 		}
 		| '-' monexpr
 		{
blob - edf2690eb3bc1fb7c13a5caeb09dfa909eafd76e
blob + 2022da53f5ab5de958b3a4a2a8381aaca285f726
--- src/cmd/acid/exec.c
+++ src/cmd/acid/exec.c
@@ -202,56 +202,6 @@ convflt(Node *r, char *flt)
 	}
 }
 
-static char*
-regbyoff(ulong addr)
-{
-	Regdesc *r;
-
-	if(mach == nil)
-		error("no mach, no registers");
-	for(r=mach->reglist; r->name; r++)
-		if(r->offset == addr)
-			return r->name;
-	error("no register at %#lux", addr);
-	return nil;
-}
-
-int
-xget1(Map *m, ulong addr, u8int *a, int n)
-{
-	if(addr < 0x100 && correg)
-		return lget1(m, correg, locreg(regbyoff(addr)), a, n);
-	else
-		return get1(m, addr, a, n);
-}
-
-int
-xget2(Map *m, ulong addr, u16int *a)
-{
-	if(addr < 0x100 && correg)
-		return lget2(m, correg, locreg(regbyoff(addr)), a);
-	else
-		return get2(m, addr, a);
-}
-
-int
-xget4(Map *m, ulong addr, u32int *a)
-{
-	if(addr < 0x100 && correg)
-		return lget4(m, correg, locreg(regbyoff(addr)), a);
-	else
-		return get4(m, addr, a);
-}
-
-int
-xget8(Map *m, ulong addr, u64int *a)
-{
-	if(addr < 0x100 && correg)
-		return lget8(m, correg, locreg(regbyoff(addr)), a);
-	else
-		return get8(m, addr, a);
-}
-
 void
 indir(Map *m, ulong addr, char fmt, Node *r)
 {
@@ -272,7 +222,7 @@ indir(Map *m, ulong addr, char fmt, Node *r)
 	case 'C':
 	case 'b':
 		r->type = TINT;
-		ret = xget1(m, addr, &cval, 1);
+		ret = get1(m, addr, &cval, 1);
 		if (ret < 0)
 			error("indir: %r");
 		r->store.u.ival = cval;
@@ -284,7 +234,7 @@ indir(Map *m, ulong addr, char fmt, Node *r)
 	case 'q':
 	case 'r':
 		r->type = TINT;
-		ret = xget2(m, addr, &sval);
+		ret = get2(m, addr, &sval);
 		if (ret < 0)
 			error("indir: %r");
 		r->store.u.ival = sval;
@@ -298,7 +248,7 @@ indir(Map *m, ulong addr, char fmt, Node *r)
 	case 'O':
 	case 'Q':
 		r->type = TINT;
-		ret = xget4(m, addr, &ival);
+		ret = get4(m, addr, &ival);
 		if (ret < 0)
 			error("indir: %r");
 		r->store.u.ival = ival;
@@ -308,7 +258,7 @@ indir(Map *m, ulong addr, char fmt, Node *r)
 	case 'Y':
 	case 'Z':
 		r->type = TINT;
-		ret = xget8(m, addr, &vval);
+		ret = get8(m, addr, &vval);
 		if (ret < 0)
 			error("indir: %r");
 		r->store.u.ival = vval;
@@ -316,7 +266,7 @@ indir(Map *m, ulong addr, char fmt, Node *r)
 	case 's':
 		r->type = TSTRING;
 		for(i = 0; i < sizeof(buf)-1; i++) {
-			ret = xget1(m, addr, (uchar*)&buf[i], 1);
+			ret = get1(m, addr, (uchar*)&buf[i], 1);
 			if (ret < 0)
 				error("indir: %r");
 			addr++;
@@ -331,7 +281,7 @@ indir(Map *m, ulong addr, char fmt, Node *r)
 	case 'R':
 		r->type = TSTRING;
 		for(i = 0; i < sizeof(buf)-2; i += 2) {
-			ret = xget1(m, addr, (uchar*)&buf[i], 2);
+			ret = get1(m, addr, (uchar*)&buf[i], 2);
 			if (ret < 0)
 				error("indir: %r");
 			addr += 2;
@@ -351,14 +301,14 @@ indir(Map *m, ulong addr, char fmt, Node *r)
 		r->store.u.string = strnode(buf);
 		break;
 	case 'f':
-		ret = xget1(m, addr, (uchar*)buf, mach->szfloat);
+		ret = get1(m, addr, (uchar*)buf, mach->szfloat);
 		if (ret < 0)
 			error("indir: %r");
 		mach->ftoa32(buf, sizeof(buf), (void*) buf);
 		convflt(r, buf);
 		break;
 	case 'g':
-		ret = xget1(m, addr, (uchar*)buf, mach->szfloat);
+		ret = get1(m, addr, (uchar*)buf, mach->szfloat);
 		if (ret < 0)
 			error("indir: %r");
 		mach->ftoa32(buf, sizeof(buf), (void*) buf);
@@ -366,14 +316,14 @@ indir(Map *m, ulong addr, char fmt, Node *r)
 		r->store.u.string = strnode(buf);
 		break;
 	case 'F':
-		ret = xget1(m, addr, (uchar*)buf, mach->szdouble);
+		ret = get1(m, addr, (uchar*)buf, mach->szdouble);
 		if (ret < 0)
 			error("indir: %r");
 		mach->ftoa64(buf, sizeof(buf), (void*) buf);
 		convflt(r, buf);
 		break;
 	case '3':	/* little endian ieee 80 with hole in bytes 8&9 */
-		ret = xget1(m, addr, (uchar*)reg, 10);
+		ret = get1(m, addr, (uchar*)reg, 10);
 		if (ret < 0)
 			error("indir: %r");
 		memmove(reg+10, reg+8, 2);	/* open hole */
@@ -382,14 +332,14 @@ indir(Map *m, ulong addr, char fmt, Node *r)
 		convflt(r, buf);
 		break;
 	case '8':	/* big-endian ieee 80 */
-		ret = xget1(m, addr, (uchar*)reg, 10);
+		ret = get1(m, addr, (uchar*)reg, 10);
 		if (ret < 0)
 			error("indir: %r");
 		beieeeftoa80(buf, sizeof(buf), reg);
 		convflt(r, buf);
 		break;
 	case 'G':
-		ret = xget1(m, addr, (uchar*)buf, mach->szdouble);
+		ret = get1(m, addr, (uchar*)buf, mach->szdouble);
 		if (ret < 0)
 			error("indir: %r");
 		mach->ftoa64(buf, sizeof(buf), (void*) buf);
@@ -400,22 +350,71 @@ indir(Map *m, ulong addr, char fmt, Node *r)
 }
 
 void
-windir(Map *m, Node *addr, Node *rval, Node *r)
+indirreg(Regs *regs, char *name, char fmt, Node *r)
 {
+	ulong val;
+
+	if(regs == 0)
+		error("no register set for *%s=", name);
+
+	r->op = OCONST;
+	r->store.fmt = fmt;
+	switch(fmt){
+	default:
+		error("bad pointer format '%c' for *%s", fmt, name);
+	case 'c':
+	case 'C':
+	case 'b':
+	case 'x':
+	case 'd':
+	case 'u':
+	case 'o':
+	case 'q':
+	case 'r':
+	case 'a':
+	case 'A':
+	case 'B':
+	case 'X':
+	case 'D':
+	case 'U':
+	case 'O':
+	case 'Q':
+	case 'V':
+	case 'W':
+	case 'Y':
+	case 'Z':
+		if(rget(regs, name, &val) < 0)
+			error("reading %s: %r", name);
+		r->type = TINT;
+		r->store.u.ival = val;
+		break;
+	case 'f':
+	case 'g':
+	case 'F':
+	case '3':
+	case '8':
+	case 'G':
+		error("floating point registers not supported");
+		break;
+	}
+}
+
+void
+windir(Map *m, Node aes, Node *rval, Node *r)
+{
 	uchar cval;
 	ushort sval;
-	Node res, aes;
+	Node res;
 	int ret;
 
 	if(m == 0)
 		error("no map for */@=");
 
-	expr(rval, &res);
-	expr(addr, &aes);
-
 	if(aes.type != TINT)
-		error("bad type lhs of @/*");
+		error("bad type lhs of */@=");
 
+	expr(rval, &res);
+
 	if(m != cormap && wtflag == 0)
 		error("not in write mode");
 
@@ -466,6 +465,58 @@ windir(Map *m, Node *addr, Node *rval, Node *r)
 }
 
 void
+windirreg(Regs *regs, char *name, Node *rval, Node *r)
+{
+	Node res;
+
+	if(regs == 0)
+		error("no register set for *%s=", name);
+
+	expr(rval, &res);
+
+	r->type = res.type;
+	r->store.fmt = res.store.fmt;
+	r->store = res.store;
+
+	switch(res.store.fmt){
+	default:
+		error("bad format '%c' for *%s=", res.store.fmt, name);
+	case 'c':
+	case 'C':
+	case 'b':
+	case 'x':
+	case 'd':
+	case 'u':
+	case 'o':
+	case 'q':
+	case 'r':
+	case 'a':
+	case 'A':
+	case 'B':
+	case 'X':
+	case 'D':
+	case 'U':
+	case 'O':
+	case 'Q':
+	case 'V':
+	case 'W':
+	case 'Y':
+	case 'Z':
+		if(rput(regs, name, res.store.u.ival) < 0)
+			error("writing %s: %r", name);
+		break;
+	case 'f':
+	case 'g':
+	case 'F':
+	case '3':
+	case '8':
+	case 'G':
+		error("floating point registers not supported");
+		break;
+	}
+}
+
+void
 call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp)
 {
 	int np, i;
blob - 9cfac9e3c5b643e68631936c31d48dd525cbe0be
blob + 6a0430dc0b520239cbdee1eec96f8cd40b845cdb
--- src/cmd/acid/expr.c
+++ src/cmd/acid/expr.c
@@ -63,11 +63,29 @@ fmtsize(Value *v)
 	}
 }
 
-void
+Lsym*
 chklval(Node *lp)
 {
-	if(lp->op != ONAME)
-		error("need l-value");
+	Node res;
+	Lsym *s;
+
+	if(lp->op == ONAME)
+		return lp->sym;
+
+	if(lp->op == OCALL){
+		s = chklval(lp->left);
+		if(strcmp(s->name, "var") == 0	
+		&& (lp->builtin || s->proc == 0)){
+			if(lp->right == 0)
+				error("var(string): arg count");
+			expr(lp->right, &res);
+			if(res.type != TSTRING)
+				error("var(string): arg type");
+			return mkvar(res.store.u.string->string);
+		}
+	}
+	error("need l-value");
+	return nil;	
 }
 
 void
@@ -107,12 +125,24 @@ oindm(Node *n, Node *res)
 	if(m == 0)
 		m = symmap;
 	expr(n->left, &l);
-	if(l.type != TINT)
+	switch(l.type){
+	default:
 		error("bad type for *");
-	if(m == 0)
-		error("no map for *");
-	indir(m, l.store.u.ival, l.store.fmt, res);
-	res->store.comt = l.store.comt;
+	case TINT:
+		if(m == 0)
+			error("no map for *");
+		indir(m, l.store.u.ival, l.store.fmt, res);
+		res->store.comt = l.store.comt;
+		break;
+	case TREG:
+		indirreg(correg, l.store.u.reg, l.store.fmt, res);
+		res->store.comt = l.store.comt;
+		break;
+	case TCON:
+		*res = *l.store.u.con;
+		res->store.comt = l.store.comt;
+		break;
+	}
 }
 
 void
@@ -145,7 +175,7 @@ oframe(Node *n, Node *res)
 	while(*p && *p == '$')
 		p++;
 	lp = n->left;
-	if(localaddr(cormap, correg, p, lp->sym->name, &ival) < 0)
+	if(localaddr(cormap, acidregs, p, lp->sym->name, &ival) < 0)
 		error("colon: %r");
 		
 	res->store.u.ival = ival;
@@ -296,19 +326,24 @@ void
 oasgn(Node *n, Node *res)
 {
 	Node *lp, r;
+	Node aes;
 	Value *v;
 
 	lp = n->left;
 	switch(lp->op) {
 	case OINDM:
-		windir(cormap, lp->left, n->right, res);
+		expr(lp->left, &aes);
+		if(aes.type == TREG)
+			windirreg(correg, aes.store.u.reg, n->right, res);
+		else
+			windir(cormap, aes, n->right, res);
 		break;
 	case OINDC:
-		windir(symmap, lp->left, n->right, res);
+		expr(lp->left, &aes);
+		windir(symmap, aes, n->right, res);
 		break;
 	default:
-		chklval(lp);
-		v = lp->sym->v;
+		v = chklval(lp)->v;
 		expr(n->right, &r);
 		v->set = 1;
 		v->type = r.type;
@@ -871,8 +906,7 @@ oeinc(Node *n, Node *res)
 {
 	Value *v;
 
-	chklval(n->left);
-	v = n->left->sym->v;
+	v = chklval(n->left)->v;
 	res->op = OCONST;
 	res->type = v->type;
 	switch(v->type) {
@@ -899,8 +933,7 @@ opinc(Node *n, Node *res)
 {
 	Value *v;
 
-	chklval(n->left);
-	v = n->left->sym->v;
+	v = chklval(n->left)->v;
 	res->op = OCONST;
 	res->type = v->type;
 	res->store = v->store;
@@ -932,9 +965,7 @@ ocall(Node *n, Node *res)
 	res->type = TLIST;
 	res->store.u.l = 0;
 
-	chklval(n->left);
-	s = n->left->sym;
-
+	s = chklval(n->left);
 	if(n->builtin && !s->builtin){
 		error("no builtin %s", s->name);
 		return;
@@ -959,6 +990,12 @@ ofmt(Node *n, Node *res)
 }
 
 void
+ouplus(Node *n, Node *res)
+{
+	expr(n->left, res);
+}
+
+void
 owhat(Node *n, Node *res)
 {
 	res->op = OCONST;		/* Default return value */
@@ -1021,6 +1058,7 @@ initexpop(void)
 	expop[OFMT] = ofmt;
 	expop[OEVAL] = oeval;
 	expop[OWHAT] = owhat;
+	expop[OUPLUS] = ouplus;
 }
 
 void
@@ -1030,3 +1068,54 @@ initexpr(void)
 	initexpop();
 }
 
+int
+acidregsrw(Regs *r, char *name, ulong *u, int isr)
+{
+	Lsym *l;
+	Value *v;
+	Node *n;
+	ulong addr;
+	u32int u32;
+
+	if(!isr){
+		werrstr("cannot write registers");
+		return -1;
+	}
+	USED(r);
+	l = look(name);
+	if(l == nil){
+		werrstr("register %s not found", name);
+		return -1;
+	}
+	v = l->v;
+	switch(v->type){
+	default:
+		werrstr("*%s: bad type", name);
+		return -1;
+	case TREG:
+		if(correg == nil){
+			werrstr("*%s: register %s not mapped", name, v->store.u.reg);
+			return -1;
+		}
+		return rget(correg, v->store.u.reg, u);
+	case TCON:
+		n = v->store.u.con;
+		if(n->op != OCONST || n->type != TINT){
+			werrstr("*%s: bad register constant", name);
+			return -1;
+		}
+		*u = n->store.u.ival;
+		return 0;
+	case TINT:
+		if(cormap == nil){
+			werrstr("*%s: core not mapped", name);
+			return -1;
+		}
+		addr = v->store.u.ival;
+		/* XXX should use format to determine size */
+		if(get4(cormap, addr, &u32) < 0)
+			return -1;
+		*u = u32;
+		return 0;
+	}
+}
blob - 87f597980b3246748f5a65228700c5a16b0df0fc
blob + e885b01dc7c7feba6a73d275acadfcca1595aefa
--- src/cmd/acid/main.c
+++ src/cmd/acid/main.c
@@ -106,6 +106,8 @@ main(int argc, char *argv[])
 	pushfile(0);
 	loadvars();
 	installbuiltin();
+	acidregs = mallocz(sizeof *acidregs, 1);
+	acidregs->rw = acidregsrw;
 
 	if(mtype && machbyname(mtype) == 0)
 		print("unknown machine %s", mtype);
@@ -170,6 +172,20 @@ main(int argc, char *argv[])
 	Bputc(bout, '\n');
 	exits(0);
 */
+}
+
+void
+setstring(char *var, char *s)
+{
+	Lsym *l;
+	Value *v;
+
+	l = mkvar(var);
+	v = l->v;
+	v->store.fmt = 's';
+	v->set = 1;
+	v->store.u.string = strnode(s ? s : "");
+	v->type = TSTRING;
 }
 
 static int
@@ -177,11 +193,10 @@ attachfiles(int argc, char **argv)
 {
 	int fd;
 	volatile int pid;
-	char *s;
+	char *s, *t;
 	int i, omode;
 	Fhdr *hdr;
 	Lsym *l;
-	Value *v;
 
 	pid = 0;
 	interactive = 0;
@@ -220,7 +235,6 @@ attachfiles(int argc, char **argv)
 		}
 		fprint(2, "%s: %s %s %s\n", argv[i], hdr->aname, hdr->mname, hdr->fname);
 		if(hdr->ftype == FCORE){
-			fprint(2, "cmd: %s\n", hdr->cmd);
 			if(pid){
 				fprint(2, "already have pid %d; ignoring core %s\n", pid, argv[i]);
 				uncrackhdr(hdr);
@@ -252,12 +266,28 @@ attachfiles(int argc, char **argv)
 				symfil = s;
 			}
 		}
-		/* XXX pull command from core */
+		if(corhdr){
+			/*
+			 * prog gives only the basename of the command,
+			 * so try the command line for a path.
+			 */
+			if((s = strdup(corhdr->cmdline)) != nil){
+				t = strchr(s, ' ');
+				if(t)
+					*t = 0;
+				if((t = searchpath(s)) != nil){
+					fprint(2, "core: text %s\n", t);
+					symfil = t;
+				}
+				free(s);
+			}
+		}
 
 		if((symhdr = crackhdr(symfil, omode)) == nil){
 			fprint(2, "crackhdr %s: %r\n", symfil);
 			symfil = nil;
-		}
+		}else
+			fprint(2, "%s: %s %s %s\n", symfil, symhdr->aname, symhdr->mname, symhdr->fname);	
 	}
 
 	if(symhdr)
@@ -281,34 +311,16 @@ attachfiles(int argc, char **argv)
 	}
 
 Run:
-	l = mkvar("objtype");
-	v = l->v;
-	v->store.fmt = 's';
-	v->set = 1;
-	v->store.u.string = strnode(mach->name);
-	v->type = TSTRING;
-
-	l = mkvar("textfile");
-	v = l->v;
-	v->store.fmt = 's';
-	v->set = 1;
-	v->store.u.string = strnode(symfil ? symfil : "");
-	v->type = TSTRING;
+	setstring("objtype", mach->name);
+	setstring("textfile", symfil);
+	setstring("systype", symhdr ? symhdr->aname : "");
+	setstring("corefile", corfil);
 
-	l = mkvar("systype");
-	v = l->v;
-	v->store.fmt = 's';
-	v->set = 1;
-	v->store.u.string = strnode(symhdr ? symhdr->aname : "");
-	v->type = TSTRING;
+	l = mkvar("pids");
+	l->v->set = 1;
+	l->v->type = TLIST;
+	l->v->store.u.l = nil;
 
-	l = mkvar("corefile");
-	v = l->v;
-	v->store.fmt = 's';
-	v->set = 1;
-	v->store.u.string = strnode(corfil ? corfil : "");
-	v->type = TSTRING;
-
 	if(pid)
 		sproc(pid);
 	if(corhdr)
@@ -320,6 +332,11 @@ Run:
 void
 setcore(Fhdr *hdr)
 {
+	int i;
+	Lsym *l;
+	Value *v;
+	List **tail, *tl;
+
 	unmapproc(cormap);
 	unmapfile(corhdr, cormap);
 	free(correg);
@@ -331,6 +348,31 @@ setcore(Fhdr *hdr)
 		error("mapfile %s: %r", hdr->filename);
 	corhdr = hdr;
 	corfil = hdr->filename;
+
+	l = mkvar("pid");
+	v = l->v;
+	v->store.fmt = 'D';
+	v->set = 1;
+	v->store.u.ival = hdr->pid;
+
+	setstring("corefile", corfil);
+	setstring("cmdline", hdr->cmdline);
+
+	l = mkvar("pids");
+	l->v->set = 1;
+	l->v->type = TLIST;
+	l->v->store.u.l = nil;
+	tail = &l->v->store.u.l;
+	for(i=0; i<hdr->nthread; i++){
+		tl = al(TINT);
+		tl->store.u.ival = hdr->thread[i].id;
+		tl->store.fmt = 'X';
+		*tail = tl;
+		tail = &tl->next;
+	}
+
+	if(hdr->nthread)
+		sproc(hdr->thread[0].id);
 }
 
 void
@@ -338,16 +380,21 @@ die(void)
 {
 	Lsym *s;
 	List *f;
+	int first;
 
 	Bprint(bout, "\n");
 
+	first = 1;
 	s = look("proclist");
 	if(s && s->v->type == TLIST) {
 		for(f = s->v->store.u.l; f; f = f->next){
 			detachproc((int)f->store.u.ival);
-			Bprint(bout, "/bin/kill -9 %d\n", (int)f->store.u.ival);
+			Bprint(bout, "%s %d", first ? "/bin/kill -9" : "", (int)f->store.u.ival);
+			first = 0;
 		}
 	}
+	if(!first)
+		Bprint(bout, "\n");
 	exits(0);
 }
 
@@ -545,6 +592,9 @@ gc(void)
 				case TCODE:
 					marktree(v->store.u.cc);
 					break;
+				case TCON:
+					marktree(v->store.u.con);
+					break;
 				}
 			}
 		}
blob - 0c66e024d92f37ef98d1b9c9c769c324da6a96cd
blob + 58acdfc9947f17d1c5d6efa1158f0e5a2dce0c9a
--- src/cmd/acid/print.c
+++ src/cmd/acid/print.c
@@ -400,6 +400,10 @@ pexpr(Node *n)
 		Bprint(bout, "whatis");
 		if(n->sym)
 			Bprint(bout, " %s", n->sym->name);
+		break;
+	case OUPLUS:
+		Bprint(bout, "+");
+		pexpr(l);
 		break;
 	}
 }
blob - a0aed614039dfb7b82164ea8944e6fb2844804c1
blob + 02c445336e819c81c4b8f546791a7e65a60a8416
--- src/cmd/acid/proc.c
+++ src/cmd/acid/proc.c
@@ -21,30 +21,39 @@ sproc(int xpid)
 	if(pid == xpid)
 		return;
 
-	if(xpid <= 0)
-		error("bad pid");
+	if(corhdr){
+		free(correg);
+		correg = nil;
+		correg = coreregs(corhdr, xpid);
+		if(correg == nil)
+			error("no such pid in core dump");
+	}else{
+		/* XXX should only change register set here if cormap already mapped */		
+		if(xpid <= 0)
+			error("bad pid");
+		unmapproc(cormap);
+		unmapfile(corhdr, cormap);
+		free(correg);
+		correg = nil;
 
-	unmapproc(cormap);
-	unmapfile(corhdr, cormap);
-	free(correg);
-	correg = nil;
+		if(mapproc(xpid, cormap, &correg) < 0)
+			error("setproc %d: %r", xpid);
 
-	if(mapproc(xpid, cormap, &correg) < 0)
-		error("setproc %d: %r", xpid);
+		/* XXX check text file here? */
 
-	/* XXX check text file here? */
-
+		for(i=0; i<cormap->nseg; i++){
+			if(cormap->seg[i].file == nil){
+				if(strcmp(cormap->seg[i].name, "data") == 0)
+					cormap->seg[i].name = "*data";
+				if(strcmp(cormap->seg[i].name, "text") == 0)
+					cormap->seg[i].name = "*text";
+			}
+		}
+	}
 	pid = xpid;
 	s = look("pid");
 	s->v->store.u.ival = pid;
 
-	for(i=0; i<cormap->nseg; i++)
-		if(cormap->seg[i].file == nil){
-			if(strcmp(cormap->seg[i].name, "data") == 0)
-				cormap->seg[i].name = "*data";
-			if(strcmp(cormap->seg[i].name, "text") == 0)
-				cormap->seg[i].name = "*text";
-		}
 	install(pid);
 }
 
@@ -165,6 +174,7 @@ install(int pid)
 	s->v->set = 1;
 }
 
+/*
 static int
 installed(int pid)
 {
@@ -175,6 +185,7 @@ installed(int pid)
 			return 1;
 	return 0;
 }
+*/
 
 void
 deinstall(int pid)
blob - 355fd5b70132339b223a18069f9a8655080c8715
blob + 3ea3c4c0265b780b006203750cd51537d46f0098
--- src/cmd/acid/util.c
+++ src/cmd/acid/util.c
@@ -61,7 +61,6 @@ varsym(void)
 			continue;
 		addvarsym(fp);
 	}
-
 	if(l->v->store.u.l == nil)
 		print("no debugging symbols\n");
 }
@@ -217,9 +216,9 @@ varreg(void)
 		l = mkvar(r->name);
 		v = l->v;
 		v->set = 1;
-		v->store.u.ival = r->offset;
+		v->store.u.reg = r->name;
 		v->store.fmt = r->format;
-		v->type = TINT;
+		v->type = TREG;
 
 		li = al(TSTRING);
 		li->store.u.string = strnode(r->name);