Mercurial > hg > Members > kono > os9 > sbc09
annotate src/trace.c @ 66:1ff0a1fdd5d7
fix xp command
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 31 Jul 2018 22:48:08 +0900 |
parents | 41f14f365b34 |
children | eb9be32c701c |
rev | line source |
---|---|
9 | 1 /* 6808 Simulator V092 |
20 | 2 * |
59 | 3 * 2018 Shinji KONO |
20 | 4 * tracer |
59 | 5 * |
0 | 6 */ |
7 | |
8 #include<stdio.h> | |
9 #include<stdlib.h> | |
10 #include<ctype.h> | |
11 #include<signal.h> | |
12 #include<sys/time.h> | |
13 | |
14 #include <unistd.h> | |
15 #include <fcntl.h> | |
16 #include <string.h> | |
1 | 17 #include <time.h> |
0 | 18 |
19 #ifdef USE_TERMIOS | |
20 #include <termios.h> | |
21 #endif | |
22 | |
23 #define engine extern | |
24 #include "v09.h" | |
25 | |
26 struct termios termsetting; | |
27 | |
28 int xmstat; /* 0= no XMODEM transfer, 1=send, 2=receiver */ | |
29 unsigned char xmbuf[132]; | |
30 int xidx; | |
31 int acknak; | |
32 int rcvdnak; | |
33 int blocknum; | |
34 | |
20 | 35 extern FILE *logfile; |
36 extern FILE *infile; | |
37 extern FILE *xfile; | |
38 extern FILE *disk[]; | |
0 | 39 |
40 extern void hexadump( unsigned char *b, int l, int loc, int w); | |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
41 extern int disasm(int,int); |
20 | 42 extern void restore_term(void) ; |
43 | |
9 | 44 #ifdef USE_MMU |
45 extern char *prog ; // for disass | |
11 | 46 extern Byte * mem0(Byte *iphymem, Word adr, Byte *immu) ; |
21 | 47 extern int paddr(Word adr, Byte *immu) ; |
48 #else | |
49 #define paddr(a,m) (a) | |
9 | 50 #endif |
51 | |
0 | 52 void do_exit(void) { |
53 restore_term(); | |
54 exit(0); | |
55 } | |
56 | |
4 | 57 |
0 | 58 typedef struct bp { |
21 | 59 int address; // physical address |
60 int laddr; | |
0 | 61 int count; |
35 | 62 int watch; // watch point |
0 | 63 struct bp *next; |
64 } BP, *BPTR; | |
65 | |
66 BPTR breakpoint = 0; | |
67 int bpskip = 0; | |
68 int trskip = 0; | |
69 int stkskip = 0; | |
70 | |
64 | 71 int getterm(char *buf, char** next) { |
72 int value = 0; | |
73 while (*buf==' ') buf++; | |
74 if (*buf=='x') { value = xreg; buf++; *next = buf ; | |
75 } else if (*buf=='y') { value = yreg; buf++; *next = buf; | |
76 } else if (*buf=='u') { value = ureg; buf++; *next = buf; | |
77 } else if (*buf=='s') { value = sreg; buf++; *next = buf; | |
78 } else if (*buf=='p') { value = pcreg; buf++; *next = buf; | |
79 } else if (*buf=='d') { value = (*areg<<8)+*breg; buf++; *next = buf; | |
80 } else if (*buf=='a') { value = *areg; buf++; *next = buf; | |
81 } else if (*buf=='b') { value = *breg; buf++; *next = buf; | |
82 } else value = strtol(buf,next,0); | |
83 return value; | |
84 } | |
85 | |
0 | 86 int getarg(char *buf, char** next) { |
64 | 87 int value = 0; |
88 char *b = buf; | |
89 if (next==0) next = &b; | |
90 value=getterm(*next,next); | |
91 for(;**next;) { | |
35 | 92 if ( **next == '+' ) { |
64 | 93 value += getterm(*next+1,next); |
35 | 94 } else if ( **next == '*' ) { |
64 | 95 value *= getterm(*next+1,next); |
35 | 96 } else if ( **next == '/' ) { |
64 | 97 value /= getterm(*next+1,next); |
35 | 98 } else if ( **next == '-' ) { |
64 | 99 value -= getterm(*next+1,next); |
35 | 100 } else if ( **next == '&' ) { |
64 | 101 value &= getterm(*next+1,next); |
35 | 102 } else if ( **next == '|' ) { |
64 | 103 value |= getterm(*next+1,next); |
104 } else if ( **next == '(' ) { | |
105 value = getarg(*next+1,next); | |
106 if(**next==')') *next=*next+1; | |
35 | 107 } else break; |
108 } | |
109 return value; | |
0 | 110 } |
111 | |
112 void printhelp(void) | |
113 { | |
114 printf( | |
64 | 115 "use 0x for hex inputs\n" |
0 | 116 " s [count] one step trace\n" |
117 " n step over\n" | |
118 " f finish this call (until stack pop)\n" | |
28 | 119 " b [adr] set break point (on current physical addreaa)\n" |
33 | 120 " B break point list\n" |
0 | 121 " d [n] delte break point list\n" |
122 " c [count] continue;\n" | |
64 | 123 " p data print\n" |
33 | 124 " x [adr] [count] dump\n" |
64 | 125 " xi [adr] [count] disassemble\n" |
9 | 126 #ifdef USE_MMU |
64 | 127 " x [p page] [offset] [count] dump physical memory\n" |
128 " xi [p page] [offset] [count] disassemble\n" | |
9 | 129 #endif |
1 | 130 " 0 file disk drive 0 image\n" |
131 " 1 file disk drive 1 image\n" | |
0 | 132 " L file start log to file\n" |
133 " S file set input file\n" | |
134 " X exit\n" | |
135 " q exit\n" | |
136 " U file upload from srecord file \n" | |
137 " D file download to srecord file \n" | |
138 " R do reset\n" | |
139 " h,? print this\n" | |
140 ); | |
141 } | |
142 | |
21 | 143 |
144 void setbreak(int adr,int count) ; | |
22 | 145 int nexti(void); |
21 | 146 |
0 | 147 void do_escape(void) { |
148 char s[80]; | |
28 | 149 int adr,page; |
38 | 150 int ppc = paddr(pcreg,mmu); |
0 | 151 if (bpskip) { // skip unbreak instruction |
152 bpskip--; | |
21 | 153 BPTR *prev = &breakpoint; |
22 | 154 for(BPTR b = breakpoint; b ; prev=&b->next, b=b->next ) { |
35 | 155 #ifdef USE_MMU |
156 int watch = phymem[b->address]; | |
157 #else | |
158 int watch = mem[b->address]; | |
159 #endif | |
160 if (ppc==b->address || b->watch != watch ) { | |
161 b->watch = watch; | |
21 | 162 if (b->count==-1) { // temporaly break point |
163 BPTR next = b->next; | |
164 free(b); | |
22 | 165 *prev = next; |
21 | 166 goto restart0; |
167 } | |
0 | 168 if (b->count) b->count--; |
169 if (b->count==0) { | |
170 goto restart0; | |
171 } | |
172 } | |
173 } | |
174 return; | |
175 } | |
176 if (stkskip) { // skip until return | |
38 | 177 #ifdef USE_MMU |
178 if (phymem[ppc]==0x3b||(phymem[ppc]==0x10&&phymem[ppc+1]==0x3f)) | |
179 goto restart0; | |
180 #else | |
181 if (mem[ppc]==0x3b||(mem[ppc]==0x10&&mem[ppc+1]==0x3f)) | |
182 goto restart0; | |
183 #endif | |
0 | 184 if (sreg < stkskip ) return; |
185 } | |
186 restart0: | |
187 stkskip = 0; | |
188 restore_term(); | |
9 | 189 #ifdef USE_MMU |
38 | 190 Byte *phyadr = phymem + ppc; |
9 | 191 prog = (char*)phyadr - pcreg; |
192 #endif | |
0 | 193 do_trace(stdout); |
194 if (trskip>1) { // show trace and step | |
195 trskip--; | |
35 | 196 int watch; // watch point |
0 | 197 set_term(escchar); |
198 return; | |
199 } | |
200 restart: | |
201 printf("v09>"); | |
28 | 202 fgets(s, sizeof(s)-1, stdin); |
203 s[strlen(s)-1] = 0; // chop | |
0 | 204 switch (s[0]) { |
64 | 205 case 'p': { |
206 int d = getarg(s+1,0); | |
207 printf("0x%x %d '%c'\n",d,d,(d<' '||d>0x7f)?' ':d); | |
208 goto restart; | |
209 } | |
21 | 210 case 'n': // step over |
211 if (nexti()) { | |
212 bpskip = -1; | |
213 break; | |
214 } | |
0 | 215 case 's': // one step trace |
216 trskip = 1; | |
217 if (s[1]) { | |
218 trskip = getarg(s+1,0); | |
219 } | |
220 bpskip = 0; | |
221 attention = escape = 1; | |
222 break; | |
223 case 'f': // finish this call (until stack pop) | |
224 stkskip = sreg + 2; | |
225 attention = escape = 1; | |
226 break; | |
227 case 'b': // set break point | |
21 | 228 if (s[1]) { |
229 char *next; | |
230 int count = 0; | |
23 | 231 int adr = getarg(s+1,&next); |
21 | 232 if (next[0]) { |
233 count = getarg(next,&next); | |
234 } | |
235 setbreak(adr,count); | |
236 } else { | |
237 setbreak(pcreg,0); | |
0 | 238 } |
239 bpskip = -1; | |
240 goto restart; | |
28 | 241 case 'B': // break point list |
0 | 242 for(BPTR bp = breakpoint; bp ; bp = bp->next) { |
21 | 243 #ifdef USE_MMU |
35 | 244 printf("0x%x p=0x%x c=%d w=0x%x\n", bp->laddr, bp->address, bp->count, bp->watch); |
21 | 245 #else |
35 | 246 printf("0x%x c=%d w=0x%x\n", bp->address, bp->count,bp->watch); |
21 | 247 #endif |
0 | 248 } |
249 goto restart; | |
250 case 'd': // delte break point list | |
251 if (s[1]) { | |
252 int trskip = getarg(s+1,0); | |
253 BPTR *prev = &breakpoint; | |
22 | 254 for(BPTR bp = breakpoint; bp ; prev=&bp->next, bp = bp->next) { |
0 | 255 if (trskip-- == 0) { |
22 | 256 BPTR next = bp->next; |
21 | 257 free(bp); |
22 | 258 *prev = next; |
0 | 259 break; |
260 } | |
261 prev = &bp->next; | |
262 } | |
263 } | |
264 goto restart; | |
265 case 'c': // continue; | |
266 bpskip = -1; | |
267 attention = escape = 1; | |
268 if (s[1]) { | |
269 bpskip = getarg(s+1,0); | |
270 } | |
271 break; | |
59 | 272 /* |
273 * we should have disassembler for a mmu page | |
274 */ | |
28 | 275 case 'x': // dump |
64 | 276 { char d = 0; |
277 char p = 0; | |
278 char *next = s+1; | |
279 int len = 32; | |
280 int adr = pcreg; | |
281 if (*next=='i') { next++; d='i'; | |
282 } | |
283 if (*next=='p') { | |
284 p = 'p'; | |
285 next++; | |
28 | 286 if (next[0]) { |
287 page = getarg(next,&next); | |
288 } | |
289 } | |
290 if (next[0]) { | |
64 | 291 adr = getarg(next,&next); |
9 | 292 #ifdef USE_MMU |
64 | 293 adr -= adr &0xf; |
66 | 294 // if (p=='p') adr -= adr&0x1fff; |
9 | 295 #endif |
64 | 296 if (next[0]) { |
297 len = getarg(next,&next); | |
298 } | |
299 } | |
300 for(; len > 0 ; len-=16,adr+=16) { | |
301 Byte *phyadr = 0; | |
9 | 302 #ifdef USE_MMU |
64 | 303 if (p=='p') { |
304 phyadr = phymem + (page * 0x2000 + adr); | |
305 prog = (char*)phyadr - adr ; | |
306 } else { | |
307 phyadr = mem0(phymem,adr,mmu); | |
308 prog = (char*)phyadr - adr ; | |
309 } | |
310 if (phyadr > phymem+memsize) goto restart; | |
9 | 311 #else |
64 | 312 phyadr = mem+adr; |
313 if (phyadr > mem+0xffff) goto restart; | |
9 | 314 #endif |
64 | 315 if (d=='i') { |
316 adr = disasm(adr,adr+(len>16?16:len)); | |
317 } else { | |
318 hexadump(phyadr,len>16?16:len,adr,16); | |
319 } | |
320 } | |
0 | 321 goto restart; |
28 | 322 } |
0 | 323 case 'L': |
324 if (logfile) | |
325 fclose(logfile); | |
326 logfile = 0; | |
327 if (s[1]) { | |
1 | 328 int i=1; while(s[i]==' ') i++; |
329 logfile = fopen(s + i, "w"); | |
0 | 330 } |
64 | 331 goto restart; |
0 | 332 break; |
333 case 'S': | |
334 if (infile) | |
335 fclose(infile); | |
336 infile = 0; | |
337 if (s[1]) { | |
1 | 338 int i=1; while(s[i]==' ') i++; |
339 infile = fopen(s + i, "r"); | |
0 | 340 } |
64 | 341 goto restart; |
0 | 342 break; |
343 case 'h': | |
344 case '?': | |
345 printhelp(); | |
346 goto restart; | |
347 case 'X': | |
348 case 'q': | |
349 if (!xmstat) | |
350 do_exit(); | |
351 else { | |
352 xmstat = 0; | |
353 fclose(xfile); | |
354 xfile = 0; | |
355 } | |
64 | 356 goto restart; |
0 | 357 break; |
1 | 358 case '0': |
359 case '1': | |
360 { FILE **drv = &disk[ s[0]-'0'] ; | |
361 if (*drv) | |
362 fclose(*drv); | |
363 *drv = 0; | |
364 if (s[1]) { | |
365 int i=1; while(s[i]==' ') i++; | |
366 *drv = fopen(s + i, "r+b"); | |
367 if ( *drv == 0 ) { printf("can't open %s\n", &s[i]); } | |
368 } | |
369 } | |
64 | 370 goto restart; |
1 | 371 break; |
0 | 372 case 'U': |
373 if (xfile) | |
374 fclose(xfile); | |
375 xfile = 0; | |
376 if (s[1]) { | |
1 | 377 int i=1; while(s[i]==' ') i++; |
378 xfile = fopen(s + i, "rb"); | |
379 if ( xfile == 0 ) { printf("can't open %s\n", &s[i]); } | |
0 | 380 } |
381 if (xfile) | |
382 xmstat = 1; | |
383 else | |
384 xmstat = 0; | |
385 xidx = 0; | |
386 acknak = 21; | |
387 rcvdnak = EOF; | |
388 blocknum = 1; | |
64 | 389 goto restart; |
0 | 390 break; |
391 case 'D': | |
392 if (xfile) | |
393 fclose(xfile); | |
394 xfile = 0; | |
395 if (s[1]) { | |
1 | 396 int i=1; while(s[i]==' ') i++; |
397 xfile = fopen(s + i, "wb"); | |
398 if ( xfile == 0 ) { printf("can't open %s\n", &s[i]); } | |
0 | 399 } |
400 if (xfile) | |
401 xmstat = 2; | |
402 else | |
403 xmstat = 0; | |
404 xidx = 0; | |
405 acknak = 21; | |
406 blocknum = 1; | |
64 | 407 goto restart; |
0 | 408 break; |
409 case 'R': | |
410 pcreg = (mem[0xfffe] << 8) + mem[0xffff]; | |
13 | 411 bpskip = 0; |
24 | 412 #ifdef USE_MMU |
413 mmu = &mem[0xffa0]; | |
28 | 414 mem[0xffa7]=0x3f; |
24 | 415 #endif |
13 | 416 attention = escape = 1; |
59 | 417 // we have to reload romfile |
418 // readimage(); | |
64 | 419 goto restart; |
0 | 420 break; |
52
51b437557f42
boot without disk image
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
38
diff
changeset
|
421 default: // one step trace |
51b437557f42
boot without disk image
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
38
diff
changeset
|
422 trskip = 1; |
51b437557f42
boot without disk image
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
38
diff
changeset
|
423 bpskip = 0; |
51b437557f42
boot without disk image
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
38
diff
changeset
|
424 attention = escape = 1; |
0 | 425 } |
426 if (tracing||breakpoint||trskip||bpskip||stkskip) { attention = escape = 1; } | |
427 else attention = 0; | |
428 set_term(escchar); | |
429 } | |
430 | |
59 | 431 /* |
432 * keep break point / watch point in a list | |
433 */ | |
21 | 434 void setbreak(int adr, int count) { |
435 BPTR bp = calloc(1,sizeof(BP)); | |
436 bp->count = count; | |
22 | 437 bp->laddr = adr; |
438 bp->address = paddr(adr,mmu); | |
35 | 439 #ifdef USE_MMU |
52
51b437557f42
boot without disk image
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
38
diff
changeset
|
440 if (bp->address >= memsize) { free(bp); return; } |
35 | 441 bp->watch = *mem0(phymem,adr,mmu); |
442 #else | |
443 bp->watch = mem[adr]; | |
444 #endif | |
52
51b437557f42
boot without disk image
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
38
diff
changeset
|
445 bp->next = breakpoint; |
51b437557f42
boot without disk image
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
38
diff
changeset
|
446 breakpoint = bp; |
21 | 447 } |
448 | |
59 | 449 /* |
64 | 450 * length of call instruction |
59 | 451 * |
64 | 452 * if next instruction is call or swi, put temporary break after the call instruction |
59 | 453 * (ignoring page boundary, sorry) |
454 */ | |
21 | 455 int nexti(void) { |
22 | 456 #ifdef USE_MMU |
457 int op1 = *mem0(phymem,pcreg,mmu); | |
458 int op2 = *mem0(phymem,pcreg+1,mmu); | |
459 #else | |
460 int op1 = mem[pcreg]; | |
461 int op2 = mem[pcreg+1]; | |
462 #endif | |
21 | 463 int ofs = 0; |
464 switch(op1) { | |
465 case 0x17: // LBSR | |
466 case 0xbd: // JSR extended | |
22 | 467 ofs=3; break; |
21 | 468 case 0x10: // page2 |
469 { | |
470 if (op2==0x3f) { // os9 system call | |
22 | 471 ofs=3; break; |
21 | 472 } |
473 } | |
29
3c14d647bb51
assembler and emulator fix
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
28
diff
changeset
|
474 break; |
21 | 475 case 0x11: // page3 |
476 { | |
477 if (op2==0x3f) { // SWI3 | |
22 | 478 ofs=2; break; |
21 | 479 } |
480 } | |
29
3c14d647bb51
assembler and emulator fix
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
28
diff
changeset
|
481 break; |
21 | 482 case 0x3f: // SWI |
22 | 483 ofs=1; break; |
21 | 484 case 0x3c: // CWAI |
485 case 0x8d: // BSR | |
486 case 0x9d: // JSR direct | |
22 | 487 ofs=2; break; |
21 | 488 case 0xad: // JSR index |
489 { | |
490 if (op2<0x80) ofs = 2; // 5bit ofs | |
491 else switch (op2&0xf) { | |
492 case 8: case 0xc: | |
493 ofs = 3; break; | |
494 case 9: case 0xd: case 0xf: | |
495 ofs = 4; break; | |
496 default: | |
497 ofs = 2; break; | |
498 } | |
499 } | |
500 break; | |
501 } | |
22 | 502 if (ofs) setbreak(pcreg+ofs,-1); |
503 return ofs; | |
21 | 504 } |
505 | |
59 | 506 /* end */ |