Mercurial > hg > Members > kono > os9 > sbc09
annotate io.c @ 9:cb7aa75418b8
mmu and io
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 05 Jul 2018 16:00:19 +0900 |
parents | a6db579d8c11 |
children | 2a1338b218bf |
rev | line source |
---|---|
9 | 1 /* 6808 Simulator V092 |
2 created 1993,1994 by L.C. Benschop. copyleft (c) 1994-2014 | |
3 by the sbc09 team, see AUTHORS for more details. license: | |
4 GNU General Public License version 2, see LICENSE for more | |
5 details. | |
0 | 6 |
7 This program simulates a 6809 processor. | |
8 | |
9 System dependencies: short must be 16 bits. | |
10 char must be 8 bits. | |
11 long must be more than 16 bits. | |
12 arrays up to 65536 bytes must be supported. | |
13 machine must be twos complement. | |
14 Most Unix machines will work. For MSODS you need long pointers | |
15 and you may have to malloc() the mem array of 65536 bytes. | |
16 | |
17 Define BIG_ENDIAN if you have a big-endian machine (680x0 etc) | |
18 | |
19 Special instructions: | |
20 SWI2 writes char to stdout from register B. | |
21 SWI3 reads char from stdout to register B, sets carry at EOF. | |
22 (or when no key available when using term control). | |
23 SWI retains its normal function. | |
24 CWAI and SYNC stop simulator. | |
25 | |
26 */ | |
27 | |
28 #include<stdio.h> | |
29 #include<stdlib.h> | |
30 #include<ctype.h> | |
31 #include<signal.h> | |
32 #include<sys/time.h> | |
33 | |
34 #include <unistd.h> | |
35 #include <fcntl.h> | |
36 #include <string.h> | |
1 | 37 #include <time.h> |
0 | 38 |
39 #ifdef USE_TERMIOS | |
40 #include <termios.h> | |
41 #endif | |
42 | |
43 #define engine extern | |
44 #include "v09.h" | |
45 | |
1 | 46 /* |
3 | 47 * IO Map ( can be overrupped by ROM ) |
48 * | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
49 * IOPAGE ~ IOPAGE+0x7f |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
50 * for OS9 level2 |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
51 * IOPAGE 0xff80 means ioport beging 0xff80 but IOPAGE itself starts 0xff00 |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
52 * 0xff00-0xff7f, 0xffe0-0xffff can be used as ROM in fixed area |
1 | 53 * |
3 | 54 * IOPAGE + 0x00 ACIA control |
55 * IOPAGE + 0x01 ACIA data | |
1 | 56 * |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
57 * IOPAGE + 0x11 MMU Taskreg 0 system map, 1 user map |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
58 * IOPAGE + 0x20-0x27 MMU reg system map |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
59 * IOPAGE + 0x28-0x2f MMU reg user map |
3 | 60 * |
61 * on reset tr==0 and only IOPAGE is valid | |
62 * translatation occur only on non-IOPAGE | |
63 * mem == phymem + 0x70000 | |
64 * phy addr = phymem[ ( mmu[ adr >> 13 ] <<13 ) + (adr & 0x1fff ) ] | |
65 * tr=0 mmu=IOPAGE+0xa0 | |
66 * tr=1 mmu=IOPAGE+0xa8 | |
1 | 67 * |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
68 * IOPAGE + 0x30 Timer control 0x8f start timer/0x80 stop timer/0x04 update date |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
69 * IOPAGE + 0x31- YY/MM/DD/HH/MM/SS |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
70 * |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
71 * IOPAGE + 0x40 Disk control 0x81 read/0x55 write 0 ... ok / 0xff .. error |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
72 * IOPAGE + 0x41 drive no |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
73 * IOPAGE + 0x42 LSN2 |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
74 * IOPAGE + 0x43 LSN1 |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
75 * IOPAGE + 0x44 LSN0 |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
76 * IOPAGE + 0x45 ADR2 |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
77 * IOPAGE + 0x46 ADR1 |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
78 * |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
79 * |
1 | 80 */ |
81 | |
82 #define SECSIZE 256 | |
83 | |
0 | 84 int tflags; |
85 int timer = 1; | |
86 struct termios termsetting; | |
87 | |
88 int xmstat; /* 0= no XMODEM transfer, 1=send, 2=receiver */ | |
89 unsigned char xmbuf[132]; | |
90 int xidx; | |
91 int acknak; | |
92 int rcvdnak; | |
93 int blocknum; | |
94 | |
95 FILE *logfile; | |
96 FILE *infile; | |
97 FILE *xfile; | |
1 | 98 FILE *disk[] = {0,0}; |
0 | 99 |
100 extern void hexadump( unsigned char *b, int l, int loc, int w); | |
101 extern void disasm(int,int); | |
9 | 102 #ifdef USE_MMU |
103 extern char *prog ; // for disass | |
104 extern Byte * mem1(Byte *iphymem, Word adr, Byte *immu) ; | |
105 #endif | |
106 | |
0 | 107 |
1 | 108 void do_timer(int,int); |
109 void do_disk(int,int); | |
4 | 110 void do_mmu(int,int); |
0 | 111 |
112 int char_input(void) { | |
113 int c, w, sum; | |
114 if (!xmstat) { | |
115 if (infile) { | |
116 c = getc(infile); | |
117 if (c == EOF) { | |
118 fclose(infile); | |
119 infile = 0; | |
120 return char_input(); | |
121 } | |
122 if (c == '\n') | |
123 c = '\r'; | |
124 return c; | |
2
31d96e2b364e
add virtual hd option to v09
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
1
diff
changeset
|
125 } else { |
31d96e2b364e
add virtual hd option to v09
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
1
diff
changeset
|
126 usleep(100); |
0 | 127 return getchar(); |
2
31d96e2b364e
add virtual hd option to v09
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
1
diff
changeset
|
128 } |
0 | 129 } else if (xmstat == 1) { |
130 if (xidx) { | |
131 c = xmbuf[xidx++]; | |
132 if (xidx == 132) { | |
133 xidx = 0; | |
134 rcvdnak = EOF; | |
135 acknak = 6; | |
136 } | |
137 } else { | |
138 if ((acknak == 21 && rcvdnak == 21) || (acknak == 6 && rcvdnak == 6)) { | |
139 rcvdnak = 0; | |
140 memset(xmbuf, 0, 132); | |
141 w = fread(xmbuf + 3, 1, 128, xfile); | |
142 if (w) { | |
143 printf("Block %3d transmitted, ", blocknum); | |
144 xmbuf[0] = 1; | |
145 xmbuf[1] = blocknum; | |
146 xmbuf[2] = 255 - blocknum; | |
147 blocknum = (blocknum + 1) & 255; | |
148 sum = 0; | |
149 for (w = 3; w < 131; w++) | |
150 sum = (sum + xmbuf[w]) & 255; | |
151 xmbuf[131] = sum; | |
152 acknak = 6; | |
153 c = 1; | |
154 xidx = 1; | |
155 } else { | |
156 printf("EOT transmitted, "); | |
157 acknak = 4; | |
158 c = 4; | |
159 } | |
160 } else if (rcvdnak == 21) { | |
161 rcvdnak = 0; | |
162 printf("Block %3d retransmitted, ", xmbuf[1]); | |
163 c = xmbuf[xidx++]; /*retransmit the same block */ | |
164 } else | |
165 c = EOF; | |
166 } | |
167 return c; | |
168 } else { | |
169 if (acknak == 4) { | |
170 c = 6; | |
171 acknak = 0; | |
172 fclose(xfile); | |
173 xfile = 0; | |
174 xmstat = 0; | |
175 } else if (acknak) { | |
176 c = acknak; | |
177 acknak = 0; | |
178 } else | |
179 c = EOF; | |
180 if (c == 6) | |
181 printf("ACK\n"); | |
182 if (c == 21) | |
183 printf("NAK\n"); | |
184 return c; | |
185 } | |
186 } | |
187 | |
9 | 188 int do_input(int a) { |
0 | 189 static int c, f = EOF; |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
190 if (a == 0+(IOPAGE&0xff)) { |
0 | 191 if (f == EOF) |
192 f = char_input(); | |
193 if (f != EOF) | |
194 c = f; | |
195 return 2 + (f != EOF); | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
196 } else if (a == 1+(IOPAGE&0xff)) { /*data port*/ |
0 | 197 if (f == EOF) |
198 f = char_input(); | |
199 if (f != EOF) { | |
200 c = f; | |
201 f = EOF; | |
202 } | |
203 return c; | |
204 } | |
9 | 205 return mem[(IOPAGE&0xff00) + a]; |
0 | 206 } |
207 | |
208 void do_output(int a, int c) { | |
209 int i, sum; | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
210 if (a == 1+(IOPAGE&0xff)) { /* ACIA data port,ignore address */ |
0 | 211 if (!xmstat) { |
212 if (logfile && c != 127 && (c >= ' ' || c == '\n')) | |
213 putc(c, logfile); | |
214 putchar(c); | |
215 fflush(stdout); | |
216 } else if (xmstat == 1) { | |
217 rcvdnak = c; | |
218 if (c == 6 && acknak == 4) { | |
219 fclose(xfile); | |
220 xfile = 0; | |
221 xmstat = 0; | |
222 } | |
223 if (c == 6) | |
224 printf("ACK\n"); | |
225 if (c == 21) | |
226 printf("NAK\n"); | |
227 if (c == 24) { | |
228 printf("CAN\n"); | |
229 fclose(xfile); | |
230 xmstat = 0; | |
231 xfile = 0; | |
232 } | |
233 } else { | |
234 if (xidx == 0 && c == 4) { | |
235 acknak = 4; | |
236 printf("EOT received, "); | |
237 } | |
238 xmbuf[xidx++] = c; | |
239 if (xidx == 132) { | |
240 sum = 0; | |
241 for (i = 3; i < 131; i++) | |
242 sum = (sum + xmbuf[i]) & 255; | |
243 if (xmbuf[0] == 1 && xmbuf[1] == 255 - xmbuf[2] | |
244 && sum == xmbuf[131]) | |
245 acknak = 6; | |
246 else | |
247 acknak = 21; | |
248 printf("Block %3d received, ", xmbuf[1]); | |
249 if (blocknum == xmbuf[1]) { | |
250 blocknum = (blocknum + 1) & 255; | |
251 fwrite(xmbuf + 3, 1, 128, xfile); | |
252 } | |
253 xidx = 0; | |
254 } | |
255 } | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
256 } else if (a >= 0x10+(IOPAGE&0xff)) { /* mmu */ |
4 | 257 do_mmu(a,c); |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
258 } else if (a >= 0x30+(IOPAGE&0xff)) { /* timer */ |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
259 do_timer(a,c); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
260 } else if (a >= 0x40+(IOPAGE&0xff)) { /* disk */ |
4 | 261 do_disk(a,c); |
0 | 262 } |
263 } | |
264 | |
265 void restore_term(void) { | |
266 tcsetattr(0, TCSAFLUSH, &termsetting); | |
267 fcntl(0, F_SETFL, tflags); | |
268 signal(SIGALRM, SIG_IGN); | |
269 } | |
270 | |
271 void do_exit(void) { | |
272 restore_term(); | |
273 exit(0); | |
274 } | |
275 | |
1 | 276 void do_timer(int a, int c) { |
277 struct itimerval timercontrol; | |
9 | 278 if (a==0x30+(IOPAGE&0xff) && c==0x8f) { |
1 | 279 timercontrol.it_interval.tv_sec = 0; |
280 timercontrol.it_interval.tv_usec = 20000; | |
281 timercontrol.it_value.tv_sec = 0; | |
282 timercontrol.it_value.tv_usec = 20000; | |
283 setitimer(ITIMER_REAL, &timercontrol, NULL); | |
9 | 284 } else if (a==0x30+(IOPAGE&0xff) && c==0x80) { |
1 | 285 timercontrol.it_interval.tv_sec = 0; |
286 timercontrol.it_interval.tv_usec = 0; | |
287 setitimer(ITIMER_REAL, &timercontrol, NULL); | |
9 | 288 } else if (a==0x30+(IOPAGE&0xff) && c==0x04) { |
1 | 289 time_t tm = time(0); |
290 struct tm *t = localtime(&tm); | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
291 mem[IOPAGE+0x31] = t->tm_year; |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
292 mem[IOPAGE+0x32] = t->tm_mon; |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
293 mem[IOPAGE+0x33] = t->tm_mday; |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
294 mem[IOPAGE+0x34] = t->tm_hour; |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
295 mem[IOPAGE+0x35] = t->tm_min; |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
296 mem[IOPAGE+0x36] = t->tm_sec; |
1 | 297 } else { |
9 | 298 mem[(IOPAGE&0xff00)+a]=c; |
1 | 299 } |
300 } | |
301 | |
302 void do_disk(int a, int c) { | |
9 | 303 if (a!=0x40+(IOPAGE&0xff)) { |
304 mem[(IOPAGE&0xff00)+a]=c; | |
1 | 305 return; |
306 } | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
307 int drv = mem[IOPAGE+0x41]; |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
308 int lsn = (mem[IOPAGE+0x42]<<16) + (mem[IOPAGE+0x43]<<8) + mem[IOPAGE+0x44]; |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
309 int buf = (mem[IOPAGE+0x45]<<8) + mem[IOPAGE+0x46]; |
1 | 310 if (drv > 1 || disk[drv]==0) goto error; |
311 if (c==0x81) { | |
312 if (lseek(fileno(disk[drv]),lsn*SECSIZE,SEEK_SET)==-1) goto error; | |
313 if (read(fileno(disk[drv]),&mem[buf],SECSIZE)==-1) goto error; | |
314 } else if (c==0x55) { | |
315 if (lseek(fileno(disk[drv]),lsn*SECSIZE,SEEK_SET)==-1) goto error; | |
316 if (write(fileno(disk[drv]),&mem[buf],SECSIZE)==-1) goto error; | |
317 } | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
318 mem[IOPAGE+0x40] = 0; |
1 | 319 return; |
320 error : | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
4
diff
changeset
|
321 mem[IOPAGE+0x40] = 0xff; |
1 | 322 } |
323 | |
4 | 324 void do_mmu(int a, int c) |
325 { | |
326 #ifdef USE_MMU | |
327 | |
9 | 328 if (a==0x11+(IOPAGE&0xff)) { |
4 | 329 if (c&0) { |
330 mmu = phymem+memsize-0x10000+0xffa0; | |
331 } else { | |
332 mmu = phymem+memsize-0x10000+0xffa8; | |
333 } | |
9 | 334 mem[(IOPAGE&0xff00)+a] = c; |
335 } if (0x20+(IOPAGE&0xff) <= a && a <= 0x2f+(IOPAGE&0xff)) { | |
336 mem[(IOPAGE&0xff00)+a] = c; | |
4 | 337 } |
338 | |
339 #endif | |
340 } | |
341 | |
0 | 342 typedef struct bp { |
343 int address; | |
344 int count; | |
345 struct bp *next; | |
346 } BP, *BPTR; | |
347 | |
348 BPTR breakpoint = 0; | |
349 int bpskip = 0; | |
350 int trskip = 0; | |
351 int stkskip = 0; | |
352 | |
353 int getarg(char *buf, char** next) { | |
354 return strtol(buf,(char**)next,0); | |
355 } | |
356 | |
357 void printhelp(void) | |
358 { | |
359 printf( | |
360 " s [count] one step trace\n" | |
361 " n step over\n" | |
362 " f finish this call (until stack pop)\n" | |
363 " b [adr] set break point\n" | |
364 " l break point list\n" | |
365 " d [n] delte break point list\n" | |
366 " c [count] continue;\n" | |
367 " x [adr] dump\n" | |
9 | 368 #ifdef USE_MMU |
369 " xp [adr] dump physical memory\n" | |
370 #endif | |
0 | 371 " xi [adr] disassemble\n" |
1 | 372 " 0 file disk drive 0 image\n" |
373 " 1 file disk drive 1 image\n" | |
0 | 374 " L file start log to file\n" |
375 " S file set input file\n" | |
376 " X exit\n" | |
377 " q exit\n" | |
378 " U file upload from srecord file \n" | |
379 " D file download to srecord file \n" | |
380 " R do reset\n" | |
381 " h,? print this\n" | |
382 ); | |
383 } | |
384 | |
385 void do_escape(void) { | |
386 char s[80]; | |
387 int adr,skip; | |
388 if (bpskip) { // skip unbreak instruction | |
389 bpskip--; | |
390 for(BPTR b = breakpoint; b ; b=b->next) { | |
391 if (pcreg==b->address) { | |
392 if (b->count) b->count--; | |
393 if (b->count==0) { | |
394 goto restart0; | |
395 } | |
396 } | |
397 } | |
398 return; | |
399 } | |
400 if (stkskip) { // skip until return | |
401 if (sreg < stkskip ) return; | |
402 } | |
403 restart0: | |
404 stkskip = 0; | |
405 restore_term(); | |
9 | 406 #ifdef USE_MMU |
407 Byte *phyadr = mem1(phymem,pcreg,mmu); | |
408 prog = (char*)phyadr - pcreg; | |
409 #endif | |
0 | 410 do_trace(stdout); |
411 if (trskip>1) { // show trace and step | |
412 trskip--; | |
413 set_term(escchar); | |
414 return; | |
415 } | |
416 restart: | |
417 printf("v09>"); | |
418 fgets(s, 80, stdin); | |
419 if (s[0]) | |
420 s[strlen(s) - 1] = 0; | |
421 switch (s[0]) { | |
422 case 's': // one step trace | |
423 trskip = 1; | |
424 if (s[1]) { | |
425 trskip = getarg(s+1,0); | |
426 } | |
427 bpskip = 0; | |
428 attention = escape = 1; | |
429 break; | |
430 case 'n': // step over | |
431 stkskip = sreg; | |
432 attention = escape = 1; | |
433 break; | |
434 case 'f': // finish this call (until stack pop) | |
435 stkskip = sreg + 2; | |
436 attention = escape = 1; | |
437 break; | |
438 case 'b': // set break point | |
439 { | |
440 BPTR bp = calloc(1,sizeof(BP)); | |
441 bp->next = breakpoint; | |
442 breakpoint = bp; | |
443 bp->count = 1; | |
444 if (s[1]) { | |
445 char *next; | |
446 bp->address = getarg(s+1,&next); | |
447 if (next[0]) { | |
448 bp->count = getarg(next,&next); | |
449 } | |
450 } else { | |
451 bp->address = pcreg; | |
452 } | |
453 } | |
454 bpskip = -1; | |
455 goto restart; | |
456 case 'l': // break point list | |
457 for(BPTR bp = breakpoint; bp ; bp = bp->next) { | |
458 printf("%x %i\n", bp->address, bp->count); | |
459 } | |
460 goto restart; | |
461 case 'd': // delte break point list | |
462 if (s[1]) { | |
463 int trskip = getarg(s+1,0); | |
464 BPTR *prev = &breakpoint; | |
465 for(BPTR bp = breakpoint; bp ; bp = bp->next) { | |
466 if (trskip-- == 0) { | |
467 if (bp) { | |
468 *prev = bp->next; | |
469 } | |
470 break; | |
471 } | |
472 prev = &bp->next; | |
473 } | |
474 } | |
475 goto restart; | |
476 case 'c': // continue; | |
477 bpskip = -1; | |
478 attention = escape = 1; | |
479 if (s[1]) { | |
480 bpskip = getarg(s+1,0); | |
481 } | |
482 break; | |
483 case 'x': // dump | |
484 skip = 1; | |
485 if (s[1]=='i') skip=2; | |
9 | 486 if (s[1]=='p') skip=2; |
0 | 487 if (s[skip]) { |
488 char *next; | |
489 int adr = getarg(s+skip,&next); | |
490 int len = 32; | |
491 if (next[0]) { | |
492 len = getarg(next,&next); | |
493 } | |
9 | 494 if (skip==2 && s[1]=='i') { |
495 for(int i=0; len > 0 ; i+=16, len-=16) { | |
496 #ifdef USE_MMU | |
497 Byte *phyadr = mem1(phymem,adr+i,mmu); | |
498 prog = (char*)phyadr - adr; | |
499 #endif | |
500 disasm(adr,adr+((i>len)?len:i)); | |
501 } | |
0 | 502 } else { |
9 | 503 #ifdef USE_MMU |
504 for(int i=0; len > 0 ; i+=16, len-=16) { | |
505 if (skip==2 && s[1]=='p') { | |
506 if (adr+i > memsize) goto restart; | |
507 hexadump(phymem+adr+i,len>16?16:len,adr+i,16); | |
508 } else { | |
509 Byte *phyadr = mem1(phymem,adr+i,mmu); | |
510 if (phyadr > phymem+memsize) goto restart; | |
511 hexadump(phyadr,len>16?16:len,adr+i,16); | |
512 } | |
513 } | |
514 #else | |
0 | 515 for(int i=0; len > 0 ; i+=16, len-=16) { |
516 hexadump(mem+adr+i,len>16?16:len,adr+i,16); | |
517 } | |
9 | 518 #endif |
0 | 519 } |
520 } else | |
521 disasm(pcreg,pcreg+32); | |
522 goto restart; | |
523 case 'L': | |
524 if (logfile) | |
525 fclose(logfile); | |
526 logfile = 0; | |
527 if (s[1]) { | |
1 | 528 int i=1; while(s[i]==' ') i++; |
529 logfile = fopen(s + i, "w"); | |
0 | 530 } |
531 break; | |
532 case 'S': | |
533 if (infile) | |
534 fclose(infile); | |
535 infile = 0; | |
536 if (s[1]) { | |
1 | 537 int i=1; while(s[i]==' ') i++; |
538 infile = fopen(s + i, "r"); | |
0 | 539 } |
540 break; | |
541 case 'h': | |
542 case '?': | |
543 printhelp(); | |
544 goto restart; | |
545 case 'X': | |
546 case 'q': | |
547 if (!xmstat) | |
548 do_exit(); | |
549 else { | |
550 xmstat = 0; | |
551 fclose(xfile); | |
552 xfile = 0; | |
553 } | |
554 break; | |
1 | 555 case '0': |
556 case '1': | |
557 { FILE **drv = &disk[ s[0]-'0'] ; | |
558 if (*drv) | |
559 fclose(*drv); | |
560 *drv = 0; | |
561 if (s[1]) { | |
562 int i=1; while(s[i]==' ') i++; | |
563 *drv = fopen(s + i, "r+b"); | |
564 if ( *drv == 0 ) { printf("can't open %s\n", &s[i]); } | |
565 } | |
566 } | |
567 break; | |
0 | 568 case 'U': |
569 if (xfile) | |
570 fclose(xfile); | |
571 xfile = 0; | |
572 if (s[1]) { | |
1 | 573 int i=1; while(s[i]==' ') i++; |
574 xfile = fopen(s + i, "rb"); | |
575 if ( xfile == 0 ) { printf("can't open %s\n", &s[i]); } | |
0 | 576 } |
577 if (xfile) | |
578 xmstat = 1; | |
579 else | |
580 xmstat = 0; | |
581 xidx = 0; | |
582 acknak = 21; | |
583 rcvdnak = EOF; | |
584 blocknum = 1; | |
585 break; | |
586 case 'D': | |
587 if (xfile) | |
588 fclose(xfile); | |
589 xfile = 0; | |
590 if (s[1]) { | |
1 | 591 int i=1; while(s[i]==' ') i++; |
592 xfile = fopen(s + i, "wb"); | |
593 if ( xfile == 0 ) { printf("can't open %s\n", &s[i]); } | |
0 | 594 } |
595 if (xfile) | |
596 xmstat = 2; | |
597 else | |
598 xmstat = 0; | |
599 xidx = 0; | |
600 acknak = 21; | |
601 blocknum = 1; | |
602 break; | |
603 case 'R': | |
604 pcreg = (mem[0xfffe] << 8) + mem[0xffff]; | |
605 break; | |
606 } | |
607 if (tracing||breakpoint||trskip||bpskip||stkskip) { attention = escape = 1; } | |
608 else attention = 0; | |
609 set_term(escchar); | |
610 } | |
611 | |
612 void timehandler(int sig) { | |
613 attention = 1; | |
614 irq = 2; | |
615 signal(SIGALRM, timehandler); | |
616 } | |
617 | |
618 void handler(int sig) { | |
619 escape = 1; | |
620 attention = 1; | |
621 bpskip = 0; | |
622 stkskip = 0; | |
623 } | |
624 | |
625 void set_term(char c) { | |
626 struct termios newterm; | |
627 struct itimerval timercontrol; | |
628 signal(SIGQUIT, SIG_IGN); | |
629 signal(SIGTSTP, SIG_IGN); | |
630 signal(SIGINT, handler); | |
631 signal(SIGUSR1, handler); | |
632 tcgetattr(0, &termsetting); | |
633 newterm = termsetting; | |
634 newterm.c_iflag = newterm.c_iflag & ~INLCR & ~ICRNL; | |
635 newterm.c_lflag = newterm.c_lflag & ~ECHO & ~ICANON; | |
636 newterm.c_cc[VTIME] = 0; | |
637 newterm.c_cc[VMIN] = 1; | |
638 newterm.c_cc[VINTR] = escchar; | |
639 tcsetattr(0, TCSAFLUSH, &newterm); | |
640 tflags = fcntl(0, F_GETFL, 0); | |
641 fcntl(0, F_SETFL, tflags | O_NDELAY); /* Make input from stdin non-blocking */ | |
642 signal(SIGALRM, timehandler); | |
643 timercontrol.it_interval.tv_sec = 0; | |
644 timercontrol.it_interval.tv_usec = 20000; | |
645 timercontrol.it_value.tv_sec = 0; | |
646 timercontrol.it_value.tv_usec = 20000; | |
647 if (timer) | |
648 setitimer(ITIMER_REAL, &timercontrol, NULL); | |
649 } |