Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <mach.h>
5
#include <ctype.h>
6
#define Extern extern
7
#include "mips.h"
8
 
9
char	buf[128], lastcmd[128];
10
char	fmt = 'X';
11
int	width = 60;
12
int	inc;
13
 
14
ulong	expr(char*);
15
ulong	expr1(char*);
16
char*	term(char*, ulong*);
17
 
18
char *
19
nextc(char *p)
20
{
21
	while(*p && (*p == ' ' || *p == '\t') && *p != '\n')
22
		p++;
23
 
24
	if(*p == '\n')
25
		*p = '\0';
26
 
27
	return p;
28
}
29
 
30
char *
31
numsym(char *addr, ulong *val)
32
{
33
	char tsym[128], *t;
34
	static char *delim = "`'<>/\\@*|-~+-/=?\n";
35
	Symbol s;
36
	char c;
37
 
38
	t = tsym;
39
	while(c = *addr) {
40
		if(strchr(delim, c))
41
			break;
42
		*t++ = c;
43
		addr++;
44
	}
45
	t[0] = '\0';
46
 
47
	if(strcmp(tsym, ".") == 0) {
48
		*val = dot;
49
		return addr;
50
	}
51
 
52
	if(lookup(0, tsym, &s))
53
		*val = s.value;
54
	else {
55
		if(tsym[0] == '#')
56
			*val = strtoul(tsym+1, 0, 16);
57
		else
58
			*val = strtoul(tsym, 0, 0);
59
	}
60
	return addr;
61
}
62
 
63
ulong
64
expr(char *addr)
65
{
66
	ulong t, t2;
67
	char op;
68
 
69
	if(*addr == '\0')
70
		return dot;
71
 
72
	addr = numsym(addr, &t);
73
 
74
	if(*addr == '\0')
75
		return t;
76
 
77
	addr = nextc(addr);
78
	op = *addr++;
79
	numsym(addr, &t2);
80
	switch(op) {
81
	default:
82
		Bprint(bioout, "expr syntax\n");
83
		return 0;
84
	case '+':
85
		t += t2;
86
		break;
87
	case '-':
88
		t -= t2;
89
		break;
90
	case '%':
91
		t /= t2;
92
		break;
93
	case '&':
94
		t &= t2;
95
		break;
96
	case '|':
97
		t |= t2;
98
		break;
99
	}
100
 
101
	return t;
102
}
103
 
104
int
105
buildargv(char *str, char **args, int max)
106
{
107
	int na = 0;
108
 
109
	while (na < max) {
110
		while((*str == ' ' || *str == '\t' || *str == '\n') && *str != '\0')
111
			str++;
112
 
113
		if(*str == '\0')
114
			return na;
115
 
116
		args[na++] = str;
117
		while(!(*str == ' ' || *str == '\t'|| *str == '\n') && *str != '\0')
118
			str++;
119
 
120
		if(*str == '\n')
121
			*str = '\0';
122
 
123
		if(*str == '\0')
124
			break;
125
 
126
		*str++ = '\0';
127
	}
128
	return na;
129
}
130
 
131
void
132
colon(char *addr, char *cp)
133
{
134
	int argc;
135
	char *argv[100];
136
	char tbuf[512];
137
 
138
	cp = nextc(cp);
139
	switch(*cp) {
140
	default:
141
		Bprint(bioout, "?\n");
142
		return;
143
	case 'b':
144
		breakpoint(addr, cp+1);
145
		return;
146
 
147
	case 'd':
148
		delbpt(addr);
149
		return;
150
 
151
	/* These fall through to print the stopped address */
152
	case 'r':
153
		reset();
154
		argc = buildargv(cp+1, argv, 100);
155
		initstk(argc, argv);
156
		count = 0;
157
		atbpt = 0;
158
		run();
159
		break;
160
	case 'c':
161
		count = 0;
162
		atbpt = 0;
163
		run();
164
		break;
165
	case 's':
166
		cp = nextc(cp+1);
167
		count = 0;
168
		if(*cp)
169
			count = strtoul(cp, 0, 0);
170
		if(count == 0)
171
			count = 1;
172
		atbpt = 0;
173
		run();
174
		break;
175
	}
176
 
177
	dot = reg.pc;
178
	Bprint(bioout, "%s at #%lux ", atbpt ? "breakpoint" : "stopped", dot);
179
	symoff(tbuf, sizeof(tbuf), dot, CTEXT);
180
	Bprint(bioout, tbuf);
181
	if(fmt == 'z')
182
		printsource(dot);
183
 
184
	Bprint(bioout, "\n");
185
}
186
 
187
 
188
void
189
dollar(char *cp)
190
{
191
	int nr;
192
 
193
	cp = nextc(cp);
194
	switch(*cp) {
195
	default:
196
		Bprint(bioout, "?\n");
197
		break;
198
 
199
	case 'c':
200
		stktrace(*cp);
201
		break;
202
 
203
	case 'C':
204
		stktrace(*cp);
205
		break;
206
 
207
	case 'b':
208
		dobplist();
209
		break;
210
 
211
	case 'r':
212
		dumpreg();
213
		break;
214
 
215
	case 'R':
216
		dumpreg();
217
 
218
	case 'f':
219
		dumpfreg();
220
		break;
221
 
222
	case 'F':
223
		dumpdreg();
224
		break;
225
 
226
	case 'q':
227
		exits(0);
228
		break;
229
 
230
	case 'Q':
231
		isum();
232
		tlbsum();
233
		segsum();
234
		break;
235
 
236
	case 't':
237
		cp++;
238
		switch(*cp) {
239
		default:
240
			Bprint(bioout, "$t[0sicr#]\n");
241
			break;
242
		case '\0':
243
			trace = 1;
244
			break;
245
		case '0':
246
			trace = 0;
247
			sysdbg = 0;
248
			calltree = 0;
249
			break;
250
		case 's':
251
			sysdbg = 1;
252
			break;
253
		case 'i':
254
			trace = 1;
255
			break;
256
		case 'c':
257
			calltree = 1;
258
			break;
259
		case 'r':
260
			nr = atoi(cp+1);
261
			if(nr < 0 || nr > 31) {
262
				print("bad register\n");
263
				break;
264
			}
265
			rtrace ^= (1<<nr);
266
			print("%.8ux\n", rtrace);
267
			break;
268
		}
269
		break;
270
 
271
	case 'i':
272
		cp++;
273
		switch(*cp) {
274
		default:
275
			Bprint(bioout, "$i[itsa]\n");
276
			break;
277
		case 'i':
278
			isum();
279
			break;
280
		case 't':
281
			tlbsum();
282
			break;
283
		case 's':
284
			segsum();
285
			break;
286
		case 'a':
287
			isum();
288
			tlbsum();
289
			segsum();
290
			iprofile();
291
			break;
292
		case 'p':
293
			iprofile();
294
			break;
295
		}
296
	}
297
}
298
 
299
int
300
pfmt(char fmt, int mem, ulong val)
301
{
302
	int c, i;
303
	Symbol s;
304
	char *p, ch, str[1024];
305
 
306
	c = 0;
307
	switch(fmt) {
308
	default:
309
		Bprint(bioout, "bad modifier\n");
310
		return 0;
311
	case 'o':
312
		c = Bprint(bioout, "%-4lo ", mem ? (ushort)getmem_2(dot) : val);
313
		inc = 2;
314
		break;
315
 
316
	case 'O':
317
		c = Bprint(bioout, "%-8lo ", mem ? getmem_4(dot) : val);
318
		inc = 4;
319
		break;
320
 
321
	case 'q':
322
		c = Bprint(bioout, "%-4lo ", mem ? (short)getmem_2(dot) : val);
323
		inc = 2;
324
		break;
325
 
326
	case 'Q':
327
		c = Bprint(bioout, "%-8lo ", mem ? (long)getmem_4(dot) : val);
328
		inc = 4;
329
		break;
330
 
331
	case 'd':
332
		c = Bprint(bioout, "%-5ld ", mem ? (short)getmem_2(dot) : val);
333
		inc = 2;
334
		break;
335
 
336
 
337
	case 'D':
338
		c = Bprint(bioout, "%-8ld ", mem ? (long)getmem_4(dot) : val);
339
		inc = 4;
340
		break;
341
 
342
	case 'x':
343
		c = Bprint(bioout, "#%-4lux ", mem ? (long)getmem_2(dot) : val);
344
		inc = 2;
345
		break;
346
 
347
	case 'X':
348
		c = Bprint(bioout, "#%-8lux ", mem ? (long)getmem_4(dot) : val);
349
		inc = 4;
350
		break;
351
 
352
	case 'u':
353
		c = Bprint(bioout, "%-5ld ", mem ? (ushort)getmem_2(dot) : val);
354
		inc = 2;
355
		break;
356
 
357
	case 'U':
358
		c = Bprint(bioout, "%-8ld ", mem ? (ulong)getmem_4(dot) : val);
359
		inc = 4;
360
		break;
361
 
362
	case 'b':
363
		c = Bprint(bioout, "%-3ld ", mem ? getmem_b(dot) : val);
364
		inc = 1;
365
		break;
366
 
367
	case 'c':
368
		c = Bprint(bioout, "%c ", (int)(mem ? getmem_b(dot) : val));
369
		inc = 1;
370
		break;
371
 
372
	case 'C':
373
		ch = mem ? getmem_b(dot) : val;
374
		if(isprint(ch))
375
			c = Bprint(bioout, "%c ", ch);
376
		else
377
			c = Bprint(bioout, "\\x%.2x ", ch);
378
		inc = 1;
379
		break;
380
 
381
	case 's':
382
		i = 0;
383
		while(ch = getmem_b(dot+i))
384
			str[i++] = ch;
385
		str[i] = '\0';
386
		dot += i;
387
		c = Bprint(bioout, "%s", str);
388
		inc = 0;
389
		break;
390
 
391
	case 'S':
392
		i = 0;
393
		while(ch = getmem_b(dot+i))
394
			str[i++] = ch;
395
		str[i] = '\0';
396
		dot += i;
397
		for(p = str; *p; p++)
398
			if(isprint(*p))
399
				c += Bprint(bioout, "%c", *p);
400
			else
401
				c += Bprint(bioout, "\\x%.2ux", *p);
402
		inc = 0;
403
		break;
404
 
405
	case 'Y':
406
		p = ctime(mem ? getmem_b(dot) : val);
407
		p[30] = '\0';
408
		c = Bprint(bioout, "%s", p);
409
		inc = 4;
410
		break;
411
 
412
	case 'a':
413
		symoff(str, sizeof(str), dot, CTEXT);
414
		c = Bprint(bioout, str);
415
		inc = 0;
416
		break;
417
 
418
	case 'e':
419
		for (i = 0; globalsym(&s, i); i++)
420
			Bprint(bioout, "%-15s #%lux\n", s.name,	getmem_4(s.value));
421
		inc = 0;
422
		break;
423
 
424
	case 'i':
425
		inc = _mipscoinst(symmap, dot, str, sizeof(str));
426
		if (inc < 0) {
427
			Bprint(bioout, "vi: %r\n");
428
			return 0;
429
		}
430
		c = Bprint(bioout, str);
431
		break;
432
 
433
	case 'n':
434
		c = width+1;
435
		inc = 0;
436
		break;
437
 
438
	case '-':
439
		c = 0;
440
		inc = -1;
441
		break;
442
 
443
	case '+':
444
		c = 0;
445
		inc = 1;
446
		break;
447
 
448
	case '^':
449
		c = 0;
450
		if(inc > 0)
451
			inc = -inc;
452
		break;
453
 
454
	case 'z':
455
		if (findsym(dot, CTEXT, &s))
456
			Bprint(bioout, "  %s() ", s.name);
457
		printsource(dot);
458
		inc = 0;
459
		break;
460
	}
461
	return c;
462
}
463
 
464
void
465
eval(char *addr, char *p)
466
{
467
	ulong val;
468
 
469
	val = expr(addr);
470
	p = nextc(p);
471
	if(*p == '\0') {
472
		p[0] = fmt;
473
		p[1] = '\0';
474
	}
475
	pfmt(*p, 0, val);
476
	Bprint(bioout, "\n");
477
}
478
 
479
void
480
quesie(char *p)
481
{
482
	int c, count, i;
483
	char tbuf[512];
484
 
485
	c = 0;
486
	symoff(tbuf, sizeof(tbuf), dot, CTEXT);
487
	Bprint(bioout, "%s?\t", tbuf);
488
 
489
	while(*p) {
490
		p = nextc(p);
491
		if(*p == '"') {
492
			for(p++; *p && *p != '"'; p++) {
493
				Bputc(bioout, *p);
494
				c++;
495
			}
496
			if(*p)
497
				p++;
498
			continue;
499
		}
500
		count = 0;
501
		while(*p >= '0' && *p <= '9')
502
			count = count*10 + (*p++ - '0');
503
		if(count == 0)
504
			count = 1;
505
		p = nextc(p);
506
		if(*p == '\0') {
507
			p[0] = fmt;
508
			p[1] = '\0';
509
		}
510
		for(i = 0; i < count; i++) {
511
			c += pfmt(*p, 1, 0);
512
			dot += inc;
513
			if(c > width) {
514
				Bprint(bioout, "\n");
515
				symoff(tbuf, sizeof(tbuf), dot, CTEXT);
516
				Bprint(bioout, "%s?\t", tbuf);
517
				c = 0;
518
			}
519
		}
520
		fmt = *p++;
521
		p = nextc(p);
522
	}
523
	Bprint(bioout, "\n");
524
}
525
 
526
void
527
catcher(void *a, char *msg)
528
{
529
	USED(a);
530
	if(strcmp(msg, "interrupt") != 0)
531
		noted(NDFLT);
532
 
533
	count = 1;
534
	print("vi\n");
535
	noted(NCONT);
536
}
537
 
538
void
539
setreg(char *addr, char *cp)
540
{
541
	int rn;
542
 
543
	dot = expr(addr);
544
	cp = nextc(cp);
545
	if(strcmp(cp, "pc") == 0) {
546
		reg.pc = dot;
547
		return;
548
	}
549
	if(strcmp(cp, "sp") == 0) {
550
		reg.r[29] = dot;
551
		return;
552
	}
553
	if(strcmp(cp, "mh") == 0) {
554
		reg.mhi = dot;
555
		return;
556
	}
557
	if(strcmp(cp, "ml") == 0) {
558
		reg.mlo = dot;
559
		return;
560
	}
561
	if(*cp++ == 'r') {
562
		rn = strtoul(cp, 0, 10);
563
		if(rn > 0 && rn < 32) {
564
			reg.r[rn] = dot;
565
			return;
566
		}
567
	}
568
	Bprint(bioout, "bad register\n");
569
}
570
 
571
void
572
cmd(void)
573
{
574
	char *p, *a, *cp, *gotint;
575
	char addr[128];
576
	static char *cmdlet = ":$?/=>";
577
	int n, i;
578
 
579
	notify(catcher);
580
 
581
	dot = reg.pc;
582
	setjmp(errjmp);
583
 
584
	for(;;) {
585
		Bflush(bioout);
586
		p = buf;
587
		n = 0;
588
		for(;;) {
589
			i = Bgetc(bin);
590
			if(i < 0)
591
				exits(0);
592
			*p++ = i;
593
			n++;
594
			if(i == '\n')
595
				break;
596
		}
597
 
598
		if(buf[0] == '\n')
599
			strcpy(buf, lastcmd);
600
		else {
601
			buf[n-1] = '\0';
602
			strcpy(lastcmd, buf);
603
		}
604
		p = buf;
605
		a = addr;
606
 
607
		for(;;) {
608
			p = nextc(p);
609
			if(*p == 0 || strchr(cmdlet, *p))
610
				break;
611
			*a++ = *p++;
612
		}
613
 
614
		*a = '\0';
615
		cmdcount = 1;
616
		cp = strchr(addr, ',');
617
		if(cp != 0) {
618
			if(cp[1] == '#')
619
				cmdcount = strtoul(cp+2, &gotint, 16);
620
			else
621
				cmdcount = strtoul(cp+1, &gotint, 0);
622
			*cp = '\0';
623
		}
624
 
625
		switch(*p) {
626
		case '$':
627
			dollar(p+1);
628
			break;
629
		case ':':
630
			colon(addr, p+1);
631
			break;
632
		case '/':
633
		case '?':
634
			dot = expr(addr);
635
			for(i = 0; i < cmdcount; i++)
636
				quesie(p+1);
637
			break;
638
		case '=':
639
			eval(addr, p+1);
640
			break;
641
		case '>':
642
			setreg(addr, p+1);
643
			break;
644
		default:
645
			Bprint(bioout, "?\n");
646
			break;
647
		}
648
	}
649
}