comparison io.c @ 0:9a224bd9b45f

os9 emulation
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 02 Jul 2018 02:12:31 +0900
parents
children 3c736a81b886
comparison
equal deleted inserted replaced
-1:000000000000 0:9a224bd9b45f
1 /* 6809 Simulator V09.
2
3 created 1993,1994 by L.C. Benschop.
4 copyleft (c) 1994-2014 by the sbc09 team, see AUTHORS for more details.
5 license: GNU General Public License version 2, see LICENSE for more details.
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>
37
38 #ifdef USE_TERMIOS
39 #include <termios.h>
40 #endif
41
42 #define engine extern
43 #include "v09.h"
44
45 int tflags;
46 int timer = 1;
47 struct termios termsetting;
48
49 int xmstat; /* 0= no XMODEM transfer, 1=send, 2=receiver */
50 unsigned char xmbuf[132];
51 int xidx;
52 int acknak;
53 int rcvdnak;
54 int blocknum;
55
56 FILE *logfile;
57 FILE *infile;
58 FILE *xfile;
59
60 extern void hexadump( unsigned char *b, int l, int loc, int w);
61 extern void disasm(int,int);
62
63
64 int char_input(void) {
65 int c, w, sum;
66 if (!xmstat) {
67 if (infile) {
68 c = getc(infile);
69 if (c == EOF) {
70 fclose(infile);
71 infile = 0;
72 return char_input();
73 }
74 if (c == '\n')
75 c = '\r';
76 return c;
77 } else
78 return getchar();
79 } else if (xmstat == 1) {
80 if (xidx) {
81 c = xmbuf[xidx++];
82 if (xidx == 132) {
83 xidx = 0;
84 rcvdnak = EOF;
85 acknak = 6;
86 }
87 } else {
88 if ((acknak == 21 && rcvdnak == 21) || (acknak == 6 && rcvdnak == 6)) {
89 rcvdnak = 0;
90 memset(xmbuf, 0, 132);
91 w = fread(xmbuf + 3, 1, 128, xfile);
92 if (w) {
93 printf("Block %3d transmitted, ", blocknum);
94 xmbuf[0] = 1;
95 xmbuf[1] = blocknum;
96 xmbuf[2] = 255 - blocknum;
97 blocknum = (blocknum + 1) & 255;
98 sum = 0;
99 for (w = 3; w < 131; w++)
100 sum = (sum + xmbuf[w]) & 255;
101 xmbuf[131] = sum;
102 acknak = 6;
103 c = 1;
104 xidx = 1;
105 } else {
106 printf("EOT transmitted, ");
107 acknak = 4;
108 c = 4;
109 }
110 } else if (rcvdnak == 21) {
111 rcvdnak = 0;
112 printf("Block %3d retransmitted, ", xmbuf[1]);
113 c = xmbuf[xidx++]; /*retransmit the same block */
114 } else
115 c = EOF;
116 }
117 return c;
118 } else {
119 if (acknak == 4) {
120 c = 6;
121 acknak = 0;
122 fclose(xfile);
123 xfile = 0;
124 xmstat = 0;
125 } else if (acknak) {
126 c = acknak;
127 acknak = 0;
128 } else
129 c = EOF;
130 if (c == 6)
131 printf("ACK\n");
132 if (c == 21)
133 printf("NAK\n");
134 return c;
135 }
136 }
137
138 int do_input( a) {
139 static int c, f = EOF;
140 if (a == 0) {
141 if (f == EOF)
142 f = char_input();
143 if (f != EOF)
144 c = f;
145 return 2 + (f != EOF);
146 } else if (a == 1) { /*data port*/
147 if (f == EOF)
148 f = char_input();
149 if (f != EOF) {
150 c = f;
151 f = EOF;
152 }
153 return c;
154 }
155 return 0;
156 }
157
158 void do_output(int a, int c) {
159 int i, sum;
160 if (a == 1) { /* ACIA data port,ignore address */
161 if (!xmstat) {
162 if (logfile && c != 127 && (c >= ' ' || c == '\n'))
163 putc(c, logfile);
164 putchar(c);
165 fflush(stdout);
166 } else if (xmstat == 1) {
167 rcvdnak = c;
168 if (c == 6 && acknak == 4) {
169 fclose(xfile);
170 xfile = 0;
171 xmstat = 0;
172 }
173 if (c == 6)
174 printf("ACK\n");
175 if (c == 21)
176 printf("NAK\n");
177 if (c == 24) {
178 printf("CAN\n");
179 fclose(xfile);
180 xmstat = 0;
181 xfile = 0;
182 }
183 } else {
184 if (xidx == 0 && c == 4) {
185 acknak = 4;
186 printf("EOT received, ");
187 }
188 xmbuf[xidx++] = c;
189 if (xidx == 132) {
190 sum = 0;
191 for (i = 3; i < 131; i++)
192 sum = (sum + xmbuf[i]) & 255;
193 if (xmbuf[0] == 1 && xmbuf[1] == 255 - xmbuf[2]
194 && sum == xmbuf[131])
195 acknak = 6;
196 else
197 acknak = 21;
198 printf("Block %3d received, ", xmbuf[1]);
199 if (blocknum == xmbuf[1]) {
200 blocknum = (blocknum + 1) & 255;
201 fwrite(xmbuf + 3, 1, 128, xfile);
202 }
203 xidx = 0;
204 }
205 }
206 }
207 }
208
209 void restore_term(void) {
210 tcsetattr(0, TCSAFLUSH, &termsetting);
211 fcntl(0, F_SETFL, tflags);
212 signal(SIGALRM, SIG_IGN);
213 }
214
215 void do_exit(void) {
216 restore_term();
217 exit(0);
218 }
219
220 typedef struct bp {
221 int address;
222 int count;
223 struct bp *next;
224 } BP, *BPTR;
225
226 BPTR breakpoint = 0;
227 int bpskip = 0;
228 int trskip = 0;
229 int stkskip = 0;
230
231 int getarg(char *buf, char** next) {
232 return strtol(buf,(char**)next,0);
233 }
234
235 void printhelp(void)
236 {
237 printf(
238 " s [count] one step trace\n"
239 " n step over\n"
240 " f finish this call (until stack pop)\n"
241 " b [adr] set break point\n"
242 " l break point list\n"
243 " d [n] delte break point list\n"
244 " c [count] continue;\n"
245 " x [adr] dump\n"
246 " xi [adr] disassemble\n"
247 " L file start log to file\n"
248 " S file set input file\n"
249 " X exit\n"
250 " q exit\n"
251 " U file upload from srecord file \n"
252 " D file download to srecord file \n"
253 " R do reset\n"
254 " h,? print this\n"
255 );
256 }
257
258 void do_escape(void) {
259 char s[80];
260 int adr,skip;
261 if (bpskip) { // skip unbreak instruction
262 bpskip--;
263 for(BPTR b = breakpoint; b ; b=b->next) {
264 if (pcreg==b->address) {
265 if (b->count) b->count--;
266 if (b->count==0) {
267 goto restart0;
268 }
269 }
270 }
271 return;
272 }
273 if (stkskip) { // skip until return
274 if (sreg < stkskip ) return;
275 }
276 restart0:
277 stkskip = 0;
278 restore_term();
279 do_trace(stdout);
280 if (trskip>1) { // show trace and step
281 trskip--;
282 set_term(escchar);
283 return;
284 }
285 restart:
286 printf("v09>");
287 fgets(s, 80, stdin);
288 if (s[0])
289 s[strlen(s) - 1] = 0;
290 switch (s[0]) {
291 case 's': // one step trace
292 trskip = 1;
293 if (s[1]) {
294 trskip = getarg(s+1,0);
295 }
296 bpskip = 0;
297 attention = escape = 1;
298 break;
299 case 'n': // step over
300 stkskip = sreg;
301 attention = escape = 1;
302 break;
303 case 'f': // finish this call (until stack pop)
304 stkskip = sreg + 2;
305 attention = escape = 1;
306 break;
307 case 'b': // set break point
308 {
309 BPTR bp = calloc(1,sizeof(BP));
310 bp->next = breakpoint;
311 breakpoint = bp;
312 bp->count = 1;
313 if (s[1]) {
314 char *next;
315 bp->address = getarg(s+1,&next);
316 if (next[0]) {
317 bp->count = getarg(next,&next);
318 }
319 } else {
320 bp->address = pcreg;
321 }
322 }
323 bpskip = -1;
324 goto restart;
325 case 'l': // break point list
326 for(BPTR bp = breakpoint; bp ; bp = bp->next) {
327 printf("%x %i\n", bp->address, bp->count);
328 }
329 goto restart;
330 case 'd': // delte break point list
331 if (s[1]) {
332 int trskip = getarg(s+1,0);
333 BPTR *prev = &breakpoint;
334 for(BPTR bp = breakpoint; bp ; bp = bp->next) {
335 if (trskip-- == 0) {
336 if (bp) {
337 *prev = bp->next;
338 }
339 break;
340 }
341 prev = &bp->next;
342 }
343 }
344 goto restart;
345 case 'c': // continue;
346 bpskip = -1;
347 attention = escape = 1;
348 if (s[1]) {
349 bpskip = getarg(s+1,0);
350 }
351 break;
352 case 'x': // dump
353 skip = 1;
354 if (s[1]=='i') skip=2;
355 if (s[skip]) {
356 char *next;
357 int adr = getarg(s+skip,&next);
358 int len = 32;
359 if (next[0]) {
360 len = getarg(next,&next);
361 }
362 if (skip==2) {
363 disasm(adr,adr+len);
364 } else {
365 for(int i=0; len > 0 ; i+=16, len-=16) {
366 hexadump(mem+adr+i,len>16?16:len,adr+i,16);
367 }
368 }
369 } else
370 disasm(pcreg,pcreg+32);
371 goto restart;
372 case 'L':
373 if (logfile)
374 fclose(logfile);
375 logfile = 0;
376 if (s[1]) {
377 logfile = fopen(s + 1, "w");
378 }
379 break;
380 case 'S':
381 if (infile)
382 fclose(infile);
383 infile = 0;
384 if (s[1]) {
385 infile = fopen(s + 1, "r");
386 }
387 break;
388 case 'h':
389 case '?':
390 printhelp();
391 goto restart;
392 case 'X':
393 case 'q':
394 if (!xmstat)
395 do_exit();
396 else {
397 xmstat = 0;
398 fclose(xfile);
399 xfile = 0;
400 }
401 break;
402 case 'U':
403 if (xfile)
404 fclose(xfile);
405 xfile = 0;
406 if (s[1]) {
407 xfile = fopen(s + 1, "rb");
408 }
409 if (xfile)
410 xmstat = 1;
411 else
412 xmstat = 0;
413 xidx = 0;
414 acknak = 21;
415 rcvdnak = EOF;
416 blocknum = 1;
417 break;
418 case 'D':
419 if (xfile)
420 fclose(xfile);
421 xfile = 0;
422 if (s[1]) {
423 xfile = fopen(s + 1, "wb");
424 }
425 if (xfile)
426 xmstat = 2;
427 else
428 xmstat = 0;
429 xidx = 0;
430 acknak = 21;
431 blocknum = 1;
432 break;
433 case 'R':
434 pcreg = (mem[0xfffe] << 8) + mem[0xffff];
435 break;
436 }
437 if (tracing||breakpoint||trskip||bpskip||stkskip) { attention = escape = 1; }
438 else attention = 0;
439 set_term(escchar);
440 }
441
442 void timehandler(int sig) {
443 attention = 1;
444 irq = 2;
445 signal(SIGALRM, timehandler);
446 }
447
448 void handler(int sig) {
449 escape = 1;
450 attention = 1;
451 bpskip = 0;
452 stkskip = 0;
453 }
454
455 void set_term(char c) {
456 struct termios newterm;
457 struct itimerval timercontrol;
458 signal(SIGQUIT, SIG_IGN);
459 signal(SIGTSTP, SIG_IGN);
460 signal(SIGINT, handler);
461 signal(SIGUSR1, handler);
462 tcgetattr(0, &termsetting);
463 newterm = termsetting;
464 newterm.c_iflag = newterm.c_iflag & ~INLCR & ~ICRNL;
465 newterm.c_lflag = newterm.c_lflag & ~ECHO & ~ICANON;
466 newterm.c_cc[VTIME] = 0;
467 newterm.c_cc[VMIN] = 1;
468 newterm.c_cc[VINTR] = escchar;
469 tcsetattr(0, TCSAFLUSH, &newterm);
470 tflags = fcntl(0, F_GETFL, 0);
471 fcntl(0, F_SETFL, tflags | O_NDELAY); /* Make input from stdin non-blocking */
472 signal(SIGALRM, timehandler);
473 timercontrol.it_interval.tv_sec = 0;
474 timercontrol.it_interval.tv_usec = 20000;
475 timercontrol.it_value.tv_sec = 0;
476 timercontrol.it_value.tv_usec = 20000;
477 if (timer)
478 setitimer(ITIMER_REAL, &timercontrol, NULL);
479 }