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