用語「デバッガー」を「モニター」に変更
[YACASL2.git] / src / exec.c
1 #include "exec.h"
2
3 /**
4  * @brief プログラムレジスタ(PR)を表すWORD値を文字列に変換
5  *
6  * @return 文字列「PR:XXXX」(Xは16進数の数字)
7  *
8  * @param pr プログラムレジスタ(PR)を表すWORD値
9  */
10 char *pr2str(WORD pr);
11
12 /**
13  * @brief 標準入力から文字データを読込(SVC 1)
14  *
15  * @return なし
16  */
17 void svcin();
18
19 /**
20  * @brief 標準出力へ文字データを書出(SVC 2)
21  *
22  * @return なし
23  */
24 void svcout();
25
26 /**
27  * @brief ロード/論理積/論理和/排他的論理和のフラグ設定。OFは常に0
28  *
29  * @return なし
30  *
31  * @param adr アドレス
32  */
33 void setfr(WORD adr);
34
35 /**
36  * @brief WORD値からr/r1を取得
37  *
38  * @return r/r1を表すWORD値
39  *
40  * @param oprx オペランドを表すWORD値
41  */
42 WORD get_r_r1(WORD oprx);
43
44 /**
45  * @brief WORD値からx/r2を取得
46  *
47  * @return x/r2を表すWORD値
48  *
49  * @param oprx オペランドを表すWORD値
50  */
51 WORD get_x_r2(WORD oprx);
52
53 /**
54  * @brief 2つのWORD値からadr[,x]を取得
55  *
56  * @return adr[,x]を表すWORD値
57  *
58  * @param adr アドレスを表すWORD値
59  * @param oprx オペランドを表すWORD値
60  */
61 WORD get_adr_x(WORD adr, WORD oprx);
62
63 /**
64  * @brief 2つのWORD値からadr[,x]のアドレスに格納されている値を取得
65  *
66  * @return adr[,x]のアドレスに格納されている値を表すWORD値
67  *
68  * @param adr アドレスを表すWORD値
69  * @param oprx オペランドを表すWORD値
70  */
71 WORD get_val_adr_x(WORD adr, WORD oprx);
72
73 /**
74  * @brief 汎用レジスタの番号からレジスタを表す文字列を返す
75  *
76  * @return 汎用レジスタを表す文字列。「GR0」「GR1」・・・「GR7」のいずれか
77  *
78  * @param word レジスタ番号[0-7]を表すWORD値
79  */
80 char *grstr(WORD word);
81
82
83 /**
84  * @brief 実行エラーの定義
85  */
86 static CERR cerr_exec[] = {
87     { 201, "Program Register (PR) - memory overflow" },
88     { 202, "Stack Pointer (SP) - stack overflow" },
89     { 203, "Stack Pointer (SP) - stack underflow" },
90     { 204, "OP in word #1 - not command code" },
91     { 205, "r/r1 in word #1 - not GR" },
92     { 206, "x/r2 in word #1 - not GR" },
93     { 207, "address in word #2 - out of memory" },
94     { 208, "SVC input - memory overflow" },
95     { 209, "SVC output - memory overflow" },
96 };
97
98 /**
99  * @brief アセンブル結果読み込みエラーの定義
100  */
101 static CERR cerr_load[] = {
102     { 210, "load - memory overflow" },
103     { 211, "object file not specified" },
104 };
105
106 /**
107  * @brief 実行モード: trace, logical, dump, step
108  */
109 EXECMODE execmode = {false, false, false, false};
110
111 char *pr2str(WORD pr)
112 {
113     char *str = malloc_chk(CERRSTRSIZE + 1, "pr2str.pr");
114
115     sprintf(str, "PR:#%04X", pr);
116     return str;
117 }
118
119 void svcin()
120 {
121     int i;
122     char *buf = malloc_chk(INSIZE + 1, "svcin.buf");
123
124     if(fgets(buf, INSIZE, stdin) == NULL) {
125         sys->memory[sys->cpu->gr[1]] = sys->memory[sys->cpu->gr[2]] = 0x0;
126         return;
127     }
128     for(i = 0; i < INSIZE; i++) {
129         if(*(buf + i) == '\0' || *(buf + i) == '\n') {
130             --i;
131             break;
132         }
133         if(sys->cpu->gr[1] + i > execptr->end) {
134             setcerr(208, "");    /* SVC input - memory overflow */
135             break;
136         }
137         sys->memory[sys->cpu->gr[1]+i] = *(buf + i);
138     }
139     sys->memory[sys->cpu->gr[2]] = i + 1;
140     FREE(buf);
141 }
142
143 void svcout()
144 {
145     int i;
146     WORD w;
147
148     for(i = 0; i < sys->memory[sys->cpu->gr[2]]; i++) {
149         if(sys->cpu->gr[1] + i > execptr->end) {
150             setcerr(209, "");    /* SVC output - memory overflow */
151             return;
152         }
153         /* 「JIS X 0201ラテン文字・片仮名用8ビット符号で規定する文字の符号表」
154            に記載された文字と、改行(CR)/タブを表示 */
155         /* それ以外の文字は、「.」で表す */
156         if(((w = sys->memory[sys->cpu->gr[1]+i]) >= 0x20 && w <= 0x7E) ||    /* JIS X 0201ラテン文字 */
157            (w >= 0xA0 && w <= 0xFE) ||                                       /* JIS X 0201片仮名用8ビット符号 */
158            w == 0xA || w == '\t')
159         {
160             putchar((char)w);
161         } else {
162             putchar('.');
163         }
164     }
165 }
166
167 void setfr(WORD adr)
168 {
169     sys->cpu->fr = 0x0;
170     /* 第15ビットが1のとき、SFは1 */
171     if((adr & 0x8000) == 0x8000) {
172         sys->cpu->fr += SF;
173     }
174     /* 演算結果が0のとき、ZFは1 */
175     if(adr == 0x0) {
176         sys->cpu->fr += ZF;
177     }
178 }
179
180 WORD get_r_r1(WORD oprx)
181 {
182     WORD r;
183     char *s;
184
185     if((r = ((oprx & 0x00F0) >>4)) > GRSIZE - 1) {
186         setcerr(205, s = pr2str(sys->cpu->pr));    /* r/r1 in word #1 - not GR */
187         FREE(s);
188         return 0x0;
189     }
190     return r;
191 }
192
193 WORD get_x_r2(WORD oprx)
194 {
195     WORD x;
196     char *s;
197
198     if((x = (oprx & 0x000F)) > GRSIZE - 1) {
199         setcerr(206, s = pr2str(sys->cpu->pr));    /* r/r1 in word #1 - not GR */
200         FREE(s);
201         return 0x0;
202     }
203     return x;
204 }
205
206 WORD get_adr_x(WORD adr, WORD oprx)
207 {
208     WORD a = adr, x;
209     if((x = get_x_r2(oprx)) > 0) {
210         a += sys->cpu->gr[x];
211     }
212     return a;
213 }
214
215 WORD get_val_adr_x(WORD adr, WORD oprx)
216 {
217     WORD a;
218     char *s;
219
220     if((a = get_adr_x(adr, oprx)) >= sys->memsize) {
221         setcerr(207, s = pr2str(sys->cpu->pr + 1));    /* address in word #2 - out of memory */
222         FREE(s);
223         return 0x0;
224     }
225     return sys->memory[a];
226 }
227
228 /* exec.hで定義された関数群 */
229 void addcerrlist_load()
230 {
231     addcerrlist(ARRAYSIZE(cerr_load), cerr_load);
232 }
233
234 void addcerrlist_exec()
235 {
236     addcerrlist(ARRAYSIZE(cerr_exec), cerr_exec);
237 }
238
239 bool loadassemble(const char *file)
240 {
241     FILE *fp;
242     bool stat = true;
243
244     assert(file != NULL);
245     if((fp = fopen(file, "rb")) == NULL) {
246         perror(file);
247         return false;
248     }
249     execptr->end = execptr->start +
250         fread(sys->memory, sizeof(WORD), sys->memsize - execptr->start, fp);
251     if(execptr->end == sys->memsize) {
252         setcerr(210, file);    /* load - memory overflow */
253         fprintf(stderr, "Load error - %d: %s\n", cerr->num, cerr->msg);
254         stat = false;
255     }
256     fclose(fp);
257     return stat;
258 }
259
260 void nop()
261 {
262     sys->cpu->pr += 1;
263 }
264
265 void ld_r_adr_x()
266 {
267     WORD w[2];
268     w[0] = sys->memory[sys->cpu->pr];
269     w[1] = sys->memory[sys->cpu->pr + 1];
270     setfr(sys->cpu->gr[get_r_r1(w[0])] = get_val_adr_x(w[1], w[0]));
271     sys->cpu->pr += 2;
272 }
273
274 void ld_r1_r2()
275 {
276     WORD w[1];
277     w[0] = sys->memory[sys->cpu->pr];
278     setfr(sys->cpu->gr[get_r_r1(w[0])] = sys->cpu->gr[get_x_r2(w[0])]);
279     sys->cpu->pr += 1;
280 }
281
282 void st()
283 {
284     WORD w[2];
285     w[0] = sys->memory[sys->cpu->pr];
286     w[1] = sys->memory[sys->cpu->pr + 1];
287     sys->memory[get_adr_x(w[1], w[0])] = sys->cpu->gr[get_r_r1(w[0])];
288     sys->cpu->pr += 2;
289 }
290
291 void lad()
292 {
293     WORD w[2];
294     w[0] = sys->memory[sys->cpu->pr];
295     w[1] = sys->memory[sys->cpu->pr + 1];
296     sys->cpu->gr[get_r_r1(w[0])] = get_adr_x(w[1], w[0]);
297     sys->cpu->pr += 2;
298 }
299
300 void adda(WORD r, WORD val)
301 {
302     long tmp;
303
304     sys->cpu->fr = 0x0;
305     /* 引数の値を16ビット符号付整数として加算し、オーバーフローをチェック */
306     assert(sizeof(short) * 8 == 16 && (short)0xFFFF == -1);
307     if((tmp = (short)(sys->cpu->gr[r]) + (short)val) > 32767 || tmp < -32768) {
308         sys->cpu->fr += OF;
309     }
310     /* 加算した結果を、WORD値に戻す */
311     sys->cpu->gr[r] = (WORD)(tmp & 0xFFFF);
312     if((sys->cpu->gr[r] & 0x8000) == 0x8000) {
313         sys->cpu->fr += SF;
314     } else if(sys->cpu->gr[r] == 0x0) {
315         sys->cpu->fr += ZF;
316     }
317 }
318
319 void adda_r_adr_x()
320 {
321     WORD w[2];
322     w[0] = sys->memory[sys->cpu->pr];
323     w[1] = sys->memory[sys->cpu->pr + 1];
324     adda(get_r_r1(w[0]), get_val_adr_x(w[1], w[0]));
325     sys->cpu->pr += 2;
326 }
327
328 void adda_r1_r2()
329 {
330     WORD w[1];
331     w[0] = sys->memory[sys->cpu->pr];
332     adda(get_r_r1(w[0]), sys->cpu->gr[get_x_r2(w[0])]);
333     sys->cpu->pr += 1;
334 }
335
336 void suba_r_adr_x()
337 {
338     WORD w[2];
339     w[0] = sys->memory[sys->cpu->pr];
340     w[1] = sys->memory[sys->cpu->pr + 1];
341     adda(get_r_r1(w[0]), ~(get_val_adr_x(w[1], w[0])) + 1);
342     sys->cpu->pr += 2;
343 }
344
345 void suba_r1_r2()
346 {
347     WORD w[1];
348     w[0] = sys->memory[sys->cpu->pr];
349     adda(get_r_r1(w[0]), ~(sys->cpu->gr[get_x_r2(w[0])]) + 1);
350     sys->cpu->pr += 1;
351 }
352
353 void addl_gr(WORD r, WORD val, bool add)
354 {
355     unsigned long o, s;
356
357     o = sys->cpu->gr[r];
358     sys->cpu->fr = 0x0;    /* flag initialize */
359
360     if(add == true) {
361         s = o + val;
362         if(s > 0xFFFF) {
363             sys->cpu->fr += OF;
364         }
365     } else {
366         if(o < val) {
367             sys->cpu->fr += OF;
368         }
369         s = o + (~val + 1);
370         if(s > 0xFFFF) {
371             s &= 0xFFFF;
372         }
373     }
374     sys->cpu->gr[r] = (WORD)s;
375
376     if((s & 0x8000) == 0x8000) {
377         sys->cpu->fr += SF;
378     }
379     else if(s == 0x0) {
380         sys->cpu->fr += ZF;
381     }
382 }
383
384 void addl_r_adr_x()
385 {
386     WORD w[2];
387     w[0] = sys->memory[sys->cpu->pr];
388     w[1] = sys->memory[sys->cpu->pr + 1];
389     addl_gr(get_r_r1(w[0]), get_val_adr_x(w[1], w[0]), true);
390     sys->cpu->pr += 2;
391 }
392
393 void addl_r1_r2()
394 {
395     WORD w[1];
396     w[0] = sys->memory[sys->cpu->pr];
397     addl_gr(get_r_r1(w[0]), sys->cpu->gr[get_x_r2(w[0])], true);
398     sys->cpu->pr += 1;
399 }
400
401 void subl_r_adr_x()
402 {
403     WORD w[2];
404     w[0] = sys->memory[sys->cpu->pr];
405     w[1] = sys->memory[sys->cpu->pr + 1];
406     addl_gr(get_r_r1(w[0]), get_val_adr_x(w[1], w[0]), false);
407     sys->cpu->pr += 2;
408 }
409
410 void subl_r1_r2()
411 {
412     WORD w[1];
413     w[0] = sys->memory[sys->cpu->pr];
414     addl_gr(get_r_r1(w[0]), sys->cpu->gr[get_x_r2(w[0])], false);
415     sys->cpu->pr += 1;
416 }
417
418 void and_r_adr_x()
419 {
420     WORD w[2];
421     w[0] = sys->memory[sys->cpu->pr];
422     w[1] = sys->memory[sys->cpu->pr + 1];
423     setfr(sys->cpu->gr[get_r_r1(w[0])] &= get_val_adr_x(w[1], w[0]));
424     sys->cpu->pr += 2;
425 }
426
427 void and_r1_r2()
428 {
429     WORD w[1];
430     w[0] = sys->memory[sys->cpu->pr];
431     setfr(sys->cpu->gr[get_r_r1(w[0])] &= sys->cpu->gr[get_x_r2(w[0])]);
432     sys->cpu->pr += 1;
433 }
434
435 void or_r_adr_x()
436 {
437     WORD w[2];
438     w[0] = sys->memory[sys->cpu->pr];
439     w[1] = sys->memory[sys->cpu->pr + 1];
440     setfr(sys->cpu->gr[get_r_r1(w[0])] |= get_val_adr_x(w[1], w[0]));
441     sys->cpu->pr += 2;
442 }
443
444 void or_r1_r2()
445 {
446     WORD w[1];
447     w[0] = sys->memory[sys->cpu->pr];
448     setfr(sys->cpu->gr[get_r_r1(w[0])] |= sys->cpu->gr[get_x_r2(w[0])]);
449     sys->cpu->pr += 1;
450 }
451
452 void xor_r_adr_x()
453 {
454     WORD w[2];
455     w[0] = sys->memory[sys->cpu->pr];
456     w[1] = sys->memory[sys->cpu->pr + 1];
457     setfr(sys->cpu->gr[get_r_r1(w[0])] ^= get_val_adr_x(w[1], w[0]));
458     sys->cpu->pr += 2;
459 }
460
461 void xor_r1_r2()
462 {
463     WORD w[1];
464     w[0] = sys->memory[sys->cpu->pr];
465     setfr(sys->cpu->gr[get_r_r1(w[0])] ^= sys->cpu->gr[get_x_r2(w[0])]);
466     sys->cpu->pr += 1;
467 }
468
469 void cpa(WORD r, WORD val)
470 {
471     sys->cpu->fr = 0x0;
472     if((short)sys->cpu->gr[r] < (short)val) {
473         sys->cpu->fr = SF;
474     } else if(sys->cpu->gr[r] == val) {
475         sys->cpu->fr = ZF;
476     }
477 }
478
479 void cpa_r_adr_x()
480 {
481     WORD w[2];
482     w[0] = sys->memory[sys->cpu->pr];
483     w[1] = sys->memory[sys->cpu->pr + 1];
484     cpa(get_r_r1(w[0]), get_val_adr_x(w[1], w[0]));
485     sys->cpu->pr += 2;
486 }
487
488 void cpa_r1_r2()
489 {
490     WORD w[1];
491     w[0] = sys->memory[sys->cpu->pr];
492     cpa(get_r_r1(w[0]), sys->cpu->gr[get_x_r2(w[0])]);
493     sys->cpu->pr += 1;
494 }
495
496 void cpl(WORD r, WORD val)
497 {
498     sys->cpu->fr = 0x0;
499     if(sys->cpu->gr[r] < val) {
500         sys->cpu->fr = SF;
501     } else if(sys->cpu->gr[r] == val) {
502         sys->cpu->fr = ZF;
503     }
504 }
505
506 void cpl_r_adr_x()
507 {
508     WORD w[2];
509     w[0] = sys->memory[sys->cpu->pr];
510     w[1] = sys->memory[sys->cpu->pr + 1];
511     cpl(get_r_r1(w[0]), get_val_adr_x(w[1], w[0]));
512     sys->cpu->pr += 2;
513 }
514
515 void cpl_r1_r2()
516 {
517     WORD w[1];
518     w[0] = sys->memory[sys->cpu->pr];
519     cpl(get_r_r1(w[0]), sys->cpu->gr[get_x_r2(w[0])]);
520     sys->cpu->pr += 1;
521 }
522
523 void sla()
524 {
525     WORD w[2], sign, last = 0x0, r;
526     int i;
527
528     w[0] = sys->memory[sys->cpu->pr];
529     w[1] = sys->memory[sys->cpu->pr + 1];
530     sys->cpu->fr = 0x0;
531     sign = sys->cpu->gr[(r = get_r_r1(w[0]))] & 0x8000;
532     sys->cpu->gr[r] &= 0x7FFF;
533     for(i = 0; i < get_adr_x(w[1], w[0]); i++) {
534         last = sys->cpu->gr[r] & 0x4000;
535         sys->cpu->gr[r] <<= 1;
536     }
537     sys->cpu->gr[r] = sign | (sys->cpu->gr[r] & 0x7FFF);
538     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
539     if(last > 0x0) {
540         sys->cpu->fr += OF;
541     }
542     /* 符号(第15ビット)が1のとき、SFは1 */
543     if(sign > 0x0) {
544         sys->cpu->fr += SF;
545     }
546     /* 演算結果が0のとき、ZFは1 */
547     if(sys->cpu->gr[r] == 0x0) {
548         sys->cpu->fr += ZF;
549     }
550     sys->cpu->pr += 2;
551 }
552
553 void sra()
554 {
555     WORD w[2], sign, last = 0x0, r;
556     int i;
557
558     w[0] = sys->memory[sys->cpu->pr];
559     w[1] = sys->memory[sys->cpu->pr + 1];
560     sys->cpu->fr = 0x0;
561     sign = sys->cpu->gr[(r = get_r_r1(w[0]))] & 0x8000;
562     sys->cpu->gr[r] &= 0x7FFF;
563     for(i = 0; i < get_adr_x(w[1], w[0]); i++) {
564         last = sys->cpu->gr[r] & 0x1;
565         sys->cpu->gr[r] >>= 1;
566         if(sign > 0) {
567             sys->cpu->gr[r] |= 0x4000;
568         }
569     }
570     sys->cpu->gr[r] = sign | sys->cpu->gr[r];
571     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
572     if(last > 0x0) {
573         sys->cpu->fr += OF;
574     }
575     /* 符号(第15ビット)が1のとき、SFは1 */
576     if(sign > 0x0) {
577         sys->cpu->fr += SF;
578     }
579     /* 演算結果が0のとき、ZFは1 */
580     if(sys->cpu->gr[r] == 0x0) {
581         sys->cpu->fr += ZF;
582     }
583     sys->cpu->pr += 2;
584 }
585
586 void sll()
587 {
588     WORD w[2], last = 0x0, r;
589     int i;
590
591     w[0] = sys->memory[sys->cpu->pr];
592     w[1] = sys->memory[sys->cpu->pr + 1];
593     sys->cpu->fr = 0x0;
594     for(i = 0; i < get_adr_x(w[1], w[0]); i++) {
595         last = sys->cpu->gr[(r = get_r_r1(w[0]))] & 0x8000;
596         sys->cpu->gr[r] <<= 1;
597     }
598     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
599     if(last > 0x0) {
600         sys->cpu->fr += OF;
601     }
602     /* 第15ビットが1のとき、SFは1 */
603     if((sys->cpu->gr[r] & 0x8000) > 0x0) {
604         sys->cpu->fr += SF;
605     }
606     /* 演算結果が0のとき、ZFは1 */
607     if(sys->cpu->gr[r] == 0x0) {
608         sys->cpu->fr += ZF;
609     }
610     sys->cpu->pr += 2;
611 }
612
613 void srl()
614 {
615     WORD w[2], last = 0x0, r;
616     int i;
617
618     w[0] = sys->memory[sys->cpu->pr];
619     w[1] = sys->memory[sys->cpu->pr + 1];
620     sys->cpu->fr = 0x0;
621     r = get_r_r1(w[0]);
622     for(i = 0; i < get_adr_x(w[1], w[0]); i++) {
623         last = sys->cpu->gr[r] & 0x0001;
624         sys->cpu->gr[r] >>= 1;
625     }
626     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
627     if(last > 0x0) {
628         sys->cpu->fr += OF;
629     }
630     /* 第15ビットが1のとき、SFは1 */
631     if((sys->cpu->gr[r] & 0x8000) > 0x0) {
632         sys->cpu->fr += SF;
633     }
634     /* 演算結果が0のとき、ZFは1 */
635     if(sys->cpu->gr[r] == 0x0) {
636         sys->cpu->fr += ZF;
637     }
638     sys->cpu->pr += 2;
639 }
640
641 void jpl()
642 {
643     WORD w[2];
644     w[0] = sys->memory[sys->cpu->pr];
645     w[1] = sys->memory[sys->cpu->pr + 1];
646     if((sys->cpu->fr & (SF | ZF)) == 0) {
647         sys->cpu->pr = get_adr_x(w[1], w[0]);
648     } else {
649         sys->cpu->pr += 2;
650     }
651 }
652
653 void jmi()
654 {
655     WORD w[2];
656     w[0] = sys->memory[sys->cpu->pr];
657     w[1] = sys->memory[sys->cpu->pr + 1];
658     if((sys->cpu->fr & SF) > 0) {
659         sys->cpu->pr = get_adr_x(w[1], w[0]);
660     } else {
661         sys->cpu->pr += 2;
662     }
663 }
664
665 void jnz()
666 {
667     WORD w[2];
668     w[0] = sys->memory[sys->cpu->pr];
669     w[1] = sys->memory[sys->cpu->pr + 1];
670     if((sys->cpu->fr & ZF) == 0) {
671         sys->cpu->pr = get_adr_x(w[1], w[0]);
672     } else {
673         sys->cpu->pr += 2;
674     }
675 }
676
677 void jze()
678 {
679     WORD w[2];
680     w[0] = sys->memory[sys->cpu->pr];
681     w[1] = sys->memory[sys->cpu->pr + 1];
682     if((sys->cpu->fr & ZF) > 0) {
683         sys->cpu->pr = get_adr_x(w[1], w[0]);
684     } else {
685         sys->cpu->pr += 2;
686     }
687 }
688
689 void jov()
690 {
691     WORD w[2];
692     w[0] = sys->memory[sys->cpu->pr];
693     w[1] = sys->memory[sys->cpu->pr + 1];
694     if((sys->cpu->fr & OF) > 0) {
695         sys->cpu->pr = get_adr_x(w[1], w[0]);
696     } else {
697         sys->cpu->pr += 2;
698     }
699 }
700
701 void jump()
702 {
703     WORD w[2];
704     w[0] = sys->memory[sys->cpu->pr];
705     w[1] = sys->memory[sys->cpu->pr + 1];
706     sys->cpu->pr = get_adr_x(w[1], w[0]);
707 }
708
709 void push()
710 {
711     assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
712     WORD w[2];
713
714     w[0] = sys->memory[sys->cpu->pr];
715     w[1] = sys->memory[sys->cpu->pr + 1];
716     sys->memory[--(sys->cpu->sp)] = get_adr_x(w[1], w[0]);
717     sys->cpu->pr += 2;
718 }
719
720 void pop()
721 {
722     assert(sys->cpu->sp > execptr->end);
723     WORD w;
724     char *s;
725
726     if(sys->cpu->sp >= sys->memsize) {
727         setcerr(203, s = pr2str(sys->cpu->pr));        /* Stack Pointer (SP) - stack underflow */
728         FREE(s);
729     } else {
730         w = sys->memory[sys->cpu->pr];
731         sys->cpu->gr[get_r_r1(w)] = sys->memory[(sys->cpu->sp)++];
732         sys->cpu->pr += 1;
733     }
734 }
735
736 void call()
737 {
738     assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
739     WORD w[2];
740     w[0] = sys->memory[sys->cpu->pr];
741     w[1] = sys->memory[sys->cpu->pr + 1];
742     sys->memory[--(sys->cpu->sp)] = sys->cpu->pr + 1;
743     sys->cpu->pr = get_adr_x(w[1], w[0]);
744 }
745
746 void ret()
747 {
748     assert(sys->cpu->sp <= sys->memsize);
749     if(sys->cpu->sp == sys->memsize) {
750         execptr->stop = true;
751     } else if(sys->cpu->sp < sys->memsize) {
752         sys->cpu->pr = sys->memory[(sys->cpu->sp)++] + 1;
753     }
754 }
755
756 void svc()
757 {
758     WORD w[2];
759     w[0] = sys->memory[sys->cpu->pr];
760     w[1] = sys->memory[sys->cpu->pr + 1];
761     switch(get_adr_x(w[1], w[0]))
762     {
763     case 0x0:                   /* STOP */
764         execptr->stop = true;
765         break;
766     case 0x1:                   /* IN */
767         svcin();
768         break;
769     case 0x2:                   /* OUT */
770         svcout();
771         break;
772     }
773     sys->cpu->pr += 2;
774 }
775
776 char *grstr(WORD word)
777 {
778     assert(word <= 7);
779     char *str = malloc_chk(3 + 1, "grstr.str");
780     sprintf(str, "GR%d", word);
781     return str;
782 }
783
784 void exec()
785 {
786     clock_t clock_begin, clock_end;
787     void (*cmdptr)();
788     char *s;
789
790     create_code_cmdtype();                          /* 命令のコードとタイプがキーのハッシュ表を作成 */
791     if(execmode.trace == true) {
792         fprintf(stdout, "\nExecuting machine codes\n");
793     }
794     /* 機械語の実行 */
795     for (sys->cpu->pr = execptr->start; ; ) {
796         clock_begin = clock();                     /* クロック周波数設定のため、実行開始時間を格納 */
797         if(execmode.dump || execmode.trace) {      /* traceまたはdumpオプション指定時、改行を出力 */
798             if(execmode.trace) {                   /* traceオプション指定時、レジスタを出力 */
799                 fprintf(stdout, "#%04X: Register::::\n", sys->cpu->pr);
800                 dspregister();
801             }
802             if(execmode.dump) {                    /* dumpオプション指定時、メモリを出力 */
803                 fprintf(stdout, "#%04X: Memory::::\n", sys->cpu->pr);
804                 dumpmemory();
805             }
806             fprintf(stdout, "\n");
807         }
808         /* デバッガーモードの場合、デバッガーを起動 */
809         if(execmode.step == true || getbps(sys->cpu->pr) == true) {
810             monitor();
811         }
812         /* プログラムレジスタをチェック */
813         if(sys->cpu->pr >= sys->memsize) {
814             setcerr(201, s = pr2str(sys->cpu->pr));        /* Program Register (PR) - memory overflow */
815             FREE(s);
816             goto execfin;
817         }
818         /* スタックポインタをチェック */
819         if(sys->cpu->sp <= execptr->end) {
820             setcerr(202, s = pr2str(sys->cpu->pr));        /* Stack Pointer (SP) - stack overflow */
821             FREE(s);
822             goto execfin;
823         }
824         /* コードから命令を取得 */
825         /* 取得できない場合はエラー終了 */
826         if((cmdptr = getcmdptr(sys->memory[sys->cpu->pr] & 0xFF00)) == NULL) {
827             setcerr(204, s = pr2str(sys->cpu->pr));            /* OP in word #1 - not command code */
828             FREE(s);
829             goto execfin;
830         }
831         /* 命令の実行 */
832         (*cmdptr)();
833         /* エラー発生時はエラー終了 */
834         if(cerr->num > 0) {
835             goto execfin;
836         }
837         /* 終了フラグがtrueの場合は、正常終了 */
838         if(execptr->stop == true) {
839             break;
840         }
841         /* クロック周波数の設定 */
842         do {
843             clock_end = clock();
844         } while(clock_end - clock_begin < CLOCKS_PER_SEC / sys->clocks);
845     }
846 execfin:
847     freebps();
848     free_code_cmdtype();                           /* 命令のコードとタイプがキーのハッシュ表を解放 */
849     if(cerr->num > 0) {
850         fprintf(stderr, "Execute error - %d: %s\n", cerr->num, cerr->msg);
851     }
852 }
853
854 bool disassemble_file(const char *file)
855 {
856     bool stat = true;
857     FILE *fp;
858     WORD i = 0, w, cmd, x, adr;
859     CMDTYPE cmdtype = 0;
860     char *cmdname, *g, *g1, *g2;
861
862     assert(file != NULL);
863     if((fp = fopen(file, "rb")) == NULL) {
864         perror(file);
865         return false;
866     }
867
868     create_code_cmdtype();                          /* 命令のコードとタイプがキーのハッシュ表を作成 */
869
870     fprintf(stdout, "MAIN\tSTART\n");
871     for(; ;) {
872         fread(&w, sizeof(WORD), 1, fp);
873         if(feof(fp)) {
874             break;
875         }
876         cmd = w & 0xFF00;
877         cmdname = getcmdname(cmd);
878         cmdtype = getcmdtype(cmd);
879         if(cmd == 0xFF00 || (w != 0 && cmd == 0x0000)) {
880             fprintf(stdout, "\tDC\t%d\t\t\t\t; #%04X: #%04X :: ", w, i++, w);
881             print_dumpword(w, true);
882         } else if(cmdtype == R_ADR_X || cmdtype == ADR_X) {
883             fread(&adr, sizeof(WORD), 1, fp);
884             fprintf(stdout, "\t%s\t", cmdname);
885             if(cmdtype == R_ADR_X) {
886                 g = grstr((w & 0x00F0) >> 4);
887                 fprintf(stdout, "%s,", g);
888                 FREE(g);
889             }
890             fprintf(stdout, "#%04X", adr);
891             if((x = w & 0x000F) != 0) {
892                 fprintf(stdout, ",%s", g = grstr(x));
893                 FREE(g);
894             }
895             fprintf(stdout, "\t\t\t\t; #%04X: #%04X #%04X", i, w, adr);
896             i += 2;
897         } else {
898             fprintf(stdout, "\t%s", cmdname);
899             if(cmdtype == R1_R2) {
900                 g1 = grstr((w & 0x00F0) >> 4);
901                 g2 = grstr(w & 0x000F);
902                 fprintf(stdout, "\t%s,%s", g1, g2);
903                 FREE(g1);
904                 FREE(g2);
905             } else if(cmdtype == R_) {
906                 g = grstr((w & 0x00F0) >> 4);
907                 fprintf(stdout, "\t%s", g);
908                 FREE(g);
909             }
910             fprintf(stdout, "\t\t\t\t; #%04X: #%04X", i++, w);
911         }
912         fprintf(stdout, "\n");
913     }
914     fprintf(stdout, "\tEND\n");
915     free_code_cmdtype();
916     fclose(fp);
917     return stat;
918 }