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 *
nextc(char * p)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 *
numsym(char * addr,ulong * val)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
expr(char * addr)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
buildargv(char * str,char ** args,int max)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
colon(char * addr,char * cp)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
dollar(char * cp)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
pfmt(char fmt,int mem,ulong val)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
eval(char * addr,char * p)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
quesie(char * p)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
catcher(void * a,char * msg)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
setreg(char * addr,char * cp)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
cmd(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 }
650