make install機能を追加
[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 stat = 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         stat = false;
70     }
71     fclose(fp);
72     return stat;
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 > execptr->end) {
103             setcerr(208, "");    /* 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 > execptr->end) {
122             setcerr(209, "");    /* 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 get_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 get_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 get_adr_x(WORD adr, WORD oprx)
181 {
182     WORD a = adr, x;
183     if((x = get_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 get_val_adr_x(WORD adr, WORD oprx)
194 {
195     WORD a;
196     if((a = get_adr_x(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  * \relates exec
206  */
207 void nop()
208 {
209     sys->cpu->pr += 1;
210 }
211
212 /**
213  * LD命令 - オペランドr,adr,x。語長2
214  * \relates exec
215  */
216 void ld_r_adr_x()
217 {
218     WORD w[2];
219     w[0] = sys->memory[sys->cpu->pr];
220     w[1] = sys->memory[sys->cpu->pr + 1];
221     setfr(sys->cpu->gr[get_r_r1(w[0])] = get_val_adr_x(w[1], w[0]));
222     sys->cpu->pr += 2;
223 }
224
225 /**
226  * LD命令 - オペランドr1,r2。語長1
227  * \relates exec
228  */
229 void ld_r1_r2()
230 {
231     WORD w[1];
232     w[0] = sys->memory[sys->cpu->pr];
233     setfr(sys->cpu->gr[get_r_r1(w[0])] = sys->cpu->gr[get_x_r2(w[0])]);
234     sys->cpu->pr += 1;
235 }
236
237 /**
238  * ST命令。語長2
239  * \relates exec
240  */
241 void st()
242 {
243     WORD w[2];
244     w[0] = sys->memory[sys->cpu->pr];
245     w[1] = sys->memory[sys->cpu->pr + 1];
246     sys->memory[get_adr_x(w[1], w[0])] = sys->cpu->gr[get_r_r1(w[0])];
247     sys->cpu->pr += 2;
248 }
249
250 /**
251  * LAD命令。語長2
252  * \relates exec
253  */
254 void lad()
255 {
256     WORD w[2];
257     w[0] = sys->memory[sys->cpu->pr];
258     w[1] = sys->memory[sys->cpu->pr + 1];
259     sys->cpu->gr[get_r_r1(w[0])] = get_adr_x(w[1], w[0]);
260     sys->cpu->pr += 2;
261 }
262
263 /**
264  * ADDA命令のテンプレート\n
265  * 汎用レジスタrに値valを算術加算
266  */
267 void adda(WORD r, WORD val)
268 {
269     long tmp;
270
271     sys->cpu->fr = 0x0;
272     /* 引数の値を16ビット符号付整数として加算し、オーバーフローをチェック */
273     assert(sizeof(short) * 8 == 16 && (short)0xFFFF == -1);
274     if((tmp = (short)(sys->cpu->gr[r]) + (short)val) > 32767 || tmp < -32768) {
275         sys->cpu->fr += OF;
276     }
277     /* 加算した結果を、WORD値に戻す */
278     sys->cpu->gr[r] = (WORD)(tmp & 0xFFFF);
279     if((sys->cpu->gr[r] & 0x8000) == 0x8000) {
280         sys->cpu->fr += SF;
281     } else if(sys->cpu->gr[r] == 0x0) {
282         sys->cpu->fr += ZF;
283     }
284 }
285
286 /**
287  * ADDA命令 - オペランドr,adr,x。語長2
288  * \relates exec
289  */
290 void adda_r_adr_x()
291 {
292     WORD w[2];
293     w[0] = sys->memory[sys->cpu->pr];
294     w[1] = sys->memory[sys->cpu->pr + 1];
295     adda(get_r_r1(w[0]), get_val_adr_x(w[1], w[0]));
296     sys->cpu->pr += 2;
297 }
298
299 /**
300  * ADDA命令 - オペランドr1,r2。語長1
301  * \relates exec
302  */
303 void adda_r1_r2()
304 {
305     WORD w[1];
306     w[0] = sys->memory[sys->cpu->pr];
307     adda(get_r_r1(w[0]), sys->cpu->gr[get_x_r2(w[0])]);
308     sys->cpu->pr += 1;
309 }
310
311 /**
312  * SUBA命令 - オペランドr,adr,x。語長2
313  * \relates exec
314  */
315 void suba_r_adr_x()
316 {
317     WORD w[2];
318     w[0] = sys->memory[sys->cpu->pr];
319     w[1] = sys->memory[sys->cpu->pr + 1];
320     adda(get_r_r1(w[0]), ~(get_val_adr_x(w[1], w[0])) + 1);
321     sys->cpu->pr += 2;
322 }
323
324 /**
325  * SUBA命令 - オペランドr1,r2。語長1
326  * \relates exec
327  */
328 void suba_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])]) + 1);
333     sys->cpu->pr += 1;
334 }
335
336 /**
337  * ADDL命令のテンプレート\n
338  * 汎用レジスタrに値valを論理加算
339  */
340 void addl(WORD r, WORD val)
341 {
342     long tmp;
343     sys->cpu->fr = 0x0;
344
345     if((tmp = sys->cpu->gr[r] + val) < 0 || tmp > 65535) {
346         sys->cpu->fr += OF;
347     }
348     if(((sys->cpu->gr[r] = (WORD)(tmp & 0xFFFF)) & 0x8000) == 0x8000) {
349         sys->cpu->fr += SF;
350     } else if(sys->cpu->gr[r] == 0x0) {
351         sys->cpu->fr += ZF;
352     }
353 }
354
355 /**
356  * ADDL命令 - オペランドr,adr,x。語長2
357  * \relates exec
358  */
359 void addl_r_adr_x()
360 {
361     WORD w[2];
362     w[0] = sys->memory[sys->cpu->pr];
363     w[1] = sys->memory[sys->cpu->pr + 1];
364     addl(get_r_r1(w[0]), get_val_adr_x(w[1], w[0]));
365     sys->cpu->pr += 2;
366 }
367
368 /**
369  * ADDL命令 - オペランドr1,r2。語長1
370  * \relates exec
371  */
372 void addl_r1_r2()
373 {
374     WORD w[1];
375     w[0] = sys->memory[sys->cpu->pr];
376     addl(get_r_r1(w[0]), sys->cpu->gr[get_x_r2(w[0])]);
377     sys->cpu->pr += 1;
378 }
379
380 /**
381  * SUBL命令 - オペランドr,adr,x。語長2
382  * \relates exec
383  */
384 void subl_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(get_r_r1(w[0]), ~(get_val_adr_x(w[1], w[0])) + 1);
390     sys->cpu->pr += 2;
391 }
392
393
394 /**
395  * SUBL命令 - オペランドr1,r2。語長1
396  * \relates exec
397  */
398 void subl_r1_r2()
399 {
400     WORD w[1];
401     w[0] = sys->memory[sys->cpu->pr];
402     addl(get_r_r1(w[0]), ~(sys->cpu->gr[get_x_r2(w[0])]) + 1);
403     sys->cpu->pr += 1;
404 }
405
406 /**
407  * AND命令 - オペランドr,adr,x。語長2
408  * \relates exec
409  */
410 void and_r_adr_x()
411 {
412     WORD w[2];
413     w[0] = sys->memory[sys->cpu->pr];
414     w[1] = sys->memory[sys->cpu->pr + 1];
415     setfr(sys->cpu->gr[get_r_r1(w[0])] &= get_val_adr_x(w[1], w[0]));
416     sys->cpu->pr += 2;
417 }
418
419 /**
420  * AND命令 - オペランドr1,r2。語長1
421  * \relates exec
422  */
423 void and_r1_r2()
424 {
425     WORD w[1];
426     w[0] = sys->memory[sys->cpu->pr];
427     setfr(sys->cpu->gr[get_r_r1(w[0])] &= sys->cpu->gr[get_x_r2(w[0])]);
428     sys->cpu->pr += 1;
429 }
430
431 /**
432  * OR命令 - オペランドr,adr,x。語長2
433  * \relates exec
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 /**
445  * OR命令 - オペランドr1,r2。語長1
446  * \relates exec
447  */
448 void or_r1_r2()
449 {
450     WORD w[1];
451     w[0] = sys->memory[sys->cpu->pr];
452     setfr(sys->cpu->gr[get_r_r1(w[0])] |= sys->cpu->gr[get_x_r2(w[0])]);
453     sys->cpu->pr += 1;
454 }
455
456 /**
457  * XOR命令 - オペランドr,adr,x。語長2
458  * \relates exec
459  */
460 void xor_r_adr_x()
461 {
462     WORD w[2];
463     w[0] = sys->memory[sys->cpu->pr];
464     w[1] = sys->memory[sys->cpu->pr + 1];
465     setfr(sys->cpu->gr[get_r_r1(w[0])] ^= get_val_adr_x(w[1], w[0]));
466     sys->cpu->pr += 2;
467 }
468
469 /**
470  * XOR命令 - オペランドr1,r2。語長1
471  * \relates exec
472  */
473 void xor_r1_r2()
474 {
475     WORD w[1];
476     w[0] = sys->memory[sys->cpu->pr];
477     setfr(sys->cpu->gr[get_r_r1(w[0])] ^= sys->cpu->gr[get_x_r2(w[0])]);
478     sys->cpu->pr += 1;
479 }
480
481 /**
482  * CPA命令のテンプレート\n
483  * 汎用レジスタrの内容と値valを算術比較
484  */
485 void cpa(WORD r, WORD val)
486 {
487     sys->cpu->fr = 0x0;
488     if((short)sys->cpu->gr[r] < (short)val) {
489         sys->cpu->fr = SF;
490     } else if(sys->cpu->gr[r] == val) {
491         sys->cpu->fr = ZF;
492     }
493 }
494
495 /**
496  * CPA命令 - オペランドr,adr,x。語長2
497  * \relates exec
498  */
499 void cpa_r_adr_x()
500 {
501     WORD w[2];
502     w[0] = sys->memory[sys->cpu->pr];
503     w[1] = sys->memory[sys->cpu->pr + 1];
504     cpa(get_r_r1(w[0]), get_val_adr_x(w[1], w[0]));
505     sys->cpu->pr += 2;
506 }
507
508 /**
509  * CPA命令 - オペランドr1,r2。語長1
510  * \relates exec
511  */
512 void cpa_r1_r2()
513 {
514     WORD w[1];
515     w[0] = sys->memory[sys->cpu->pr];
516     cpa(get_r_r1(w[0]), sys->cpu->gr[get_x_r2(w[0])]);
517     sys->cpu->pr += 1;
518 }
519
520 /**
521  * CPL命令のテンプレート\n
522  * 汎用レジスタrの内容と値valを論理比較
523  */
524 void cpl(WORD r, WORD val)
525 {
526     sys->cpu->fr = 0x0;
527     if(sys->cpu->gr[r] < val) {
528         sys->cpu->fr = SF;
529     } else if(sys->cpu->gr[r] == val) {
530         sys->cpu->fr = ZF;
531     }
532 }
533
534
535 /**
536  * CPL命令 - オペランドr,adr,x。語長2
537  * \relates exec
538  */
539 void cpl_r_adr_x()
540 {
541     WORD w[2];
542     w[0] = sys->memory[sys->cpu->pr];
543     w[1] = sys->memory[sys->cpu->pr + 1];
544     cpl(get_r_r1(w[0]), get_val_adr_x(w[1], w[0]));
545     sys->cpu->pr += 2;
546 }
547
548 /**
549  * CPL命令 - オペランドr1,r2。語長1
550  * \relates exec
551  */
552 void cpl_r1_r2()
553 {
554     WORD w[1];
555     w[0] = sys->memory[sys->cpu->pr];
556     cpl(get_r_r1(w[0]), sys->cpu->gr[get_x_r2(w[0])]);
557     sys->cpu->pr += 1;
558 }
559
560 /**
561  * SLA命令 - オペランドr,adr,x。語長2\n
562  * 算術演算なので、第15ビットは送り出されない
563  * \relates exec
564  */
565 void sla()
566 {
567     WORD w[2], sign, last = 0x0, r;
568     int i;
569
570     w[0] = sys->memory[sys->cpu->pr];
571     w[1] = sys->memory[sys->cpu->pr + 1];
572     sys->cpu->fr = 0x0;
573     sign = sys->cpu->gr[(r = get_r_r1(w[0]))] & 0x8000;
574     sys->cpu->gr[r] &= 0x7FFF;
575     for(i = 0; i < get_adr_x(w[1], w[0]); i++) {
576         last = sys->cpu->gr[r] & 0x4000;
577         sys->cpu->gr[r] <<= 1;
578     }
579     sys->cpu->gr[r] = sign | (sys->cpu->gr[r] & 0x7FFF);
580     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
581     if(last > 0x0) {
582         sys->cpu->fr += OF;
583     }
584     /* 符号(第15ビット)が1のとき、SFは1 */
585     if(sign > 0x0) {
586         sys->cpu->fr += SF;
587     }
588     /* 演算結果が0のとき、ZFは1 */
589     if(sys->cpu->gr[r] == 0x0) {
590         sys->cpu->fr += ZF;
591     }
592     sys->cpu->pr += 2;
593 }
594
595 /**
596  * SRA命令 - オペランドr,adr,x。語長2\n
597  * 算術演算なので、第15ビットは送り出されない\n
598  * 空いたビット位置には符号と同じものが入る
599  * \relates exec
600  */
601 void sra()
602 {
603     WORD w[2], sign, last = 0x0, r;
604     int i;
605
606     w[0] = sys->memory[sys->cpu->pr];
607     w[1] = sys->memory[sys->cpu->pr + 1];
608     sys->cpu->fr = 0x0;
609     sign = sys->cpu->gr[(r = get_r_r1(w[0]))] & 0x8000;
610     sys->cpu->gr[r] &= 0x7FFF;
611     for(i = 0; i < get_adr_x(w[1], w[0]); i++) {
612         last = sys->cpu->gr[r] & 0x1;
613         sys->cpu->gr[r] >>= 1;
614         if(sign > 0) {
615             sys->cpu->gr[r] |= 0x4000;
616         }
617     }
618     sys->cpu->gr[r] = sign | sys->cpu->gr[r];
619     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
620     if(last > 0x0) {
621         sys->cpu->fr += OF;
622     }
623     /* 符号(第15ビット)が1のとき、SFは1 */
624     if(sign > 0x0) {
625         sys->cpu->fr += SF;
626     }
627     /* 演算結果が0のとき、ZFは1 */
628     if(sys->cpu->gr[r] == 0x0) {
629         sys->cpu->fr += ZF;
630     }
631     sys->cpu->pr += 2;
632 }
633
634 /**
635  * SLL命令 - オペランドr,adr,x。語長2
636  * \relates exec
637  */
638 void sll()
639 {
640     WORD w[2], last = 0x0, r;
641     int i;
642
643     w[0] = sys->memory[sys->cpu->pr];
644     w[1] = sys->memory[sys->cpu->pr + 1];
645     sys->cpu->fr = 0x0;
646     for(i = 0; i < get_adr_x(w[1], w[0]); i++) {
647         last = sys->cpu->gr[(r = get_r_r1(w[0]))] & 0x8000;
648         sys->cpu->gr[r] <<= 1;
649     }
650     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
651     if(last > 0x0) {
652         sys->cpu->fr += OF;
653     }
654     /* 第15ビットが1のとき、SFは1 */
655     if((sys->cpu->gr[r] & 0x8000) > 0x0) {
656         sys->cpu->fr += SF;
657     }
658     /* 演算結果が0のとき、ZFは1 */
659     if(sys->cpu->gr[r] == 0x0) {
660         sys->cpu->fr += ZF;
661     }
662     sys->cpu->pr += 2;
663 }
664
665 /**
666  * SRL命令 - オペランドr,adr,x。語長2
667  * \relates exec
668  */
669 void srl()
670 {
671     WORD w[2], last = 0x0, r;
672     int i;
673
674     w[0] = sys->memory[sys->cpu->pr];
675     w[1] = sys->memory[sys->cpu->pr + 1];
676     sys->cpu->fr = 0x0;
677     r = get_r_r1(w[0]);
678     for(i = 0; i < get_adr_x(w[1], w[0]); i++) {
679         last = sys->cpu->gr[r] & 0x0001;
680         sys->cpu->gr[r] >>= 1;
681     }
682     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
683     if(last > 0x0) {
684         sys->cpu->fr += OF;
685     }
686     /* 第15ビットが1のとき、SFは1 */
687     if((sys->cpu->gr[r] & 0x8000) > 0x0) {
688         sys->cpu->fr += SF;
689     }
690     /* 演算結果が0のとき、ZFは1 */
691     if(sys->cpu->gr[r] == 0x0) {
692         sys->cpu->fr += ZF;
693     }
694     sys->cpu->pr += 2;
695 }
696
697 /**
698  * JPL命令。語長2
699  * \relates exec
700  */
701 void jpl()
702 {
703     WORD w[2];
704     w[0] = sys->memory[sys->cpu->pr];
705     w[1] = sys->memory[sys->cpu->pr + 1];
706     if((sys->cpu->fr & (SF | ZF)) == 0) {
707         sys->cpu->pr = get_adr_x(w[1], w[0]);
708     } else {
709         sys->cpu->pr += 2;
710     }
711 }
712
713 /**
714  * JMI命令。語長2
715  * \relates exec
716  */
717 void jmi()
718 {
719     WORD w[2];
720     w[0] = sys->memory[sys->cpu->pr];
721     w[1] = sys->memory[sys->cpu->pr + 1];
722     if((sys->cpu->fr & SF) > 0) {
723         sys->cpu->pr = get_adr_x(w[1], w[0]);
724     } else {
725         sys->cpu->pr += 2;
726     }
727 }
728
729 /**
730  * JNZ命令。語長2
731  * \relates exec
732  */
733 void jnz()
734 {
735     WORD w[2];
736     w[0] = sys->memory[sys->cpu->pr];
737     w[1] = sys->memory[sys->cpu->pr + 1];
738     if((sys->cpu->fr & ZF) == 0) {
739         sys->cpu->pr = get_adr_x(w[1], w[0]);
740     } else {
741         sys->cpu->pr += 2;
742     }
743 }
744
745 /**
746  * JZE命令。語長2
747  * \relates exec
748  */
749 void jze()
750 {
751     WORD w[2];
752     w[0] = sys->memory[sys->cpu->pr];
753     w[1] = sys->memory[sys->cpu->pr + 1];
754     if((sys->cpu->fr & ZF) > 0) {
755         sys->cpu->pr = get_adr_x(w[1], w[0]);
756     } else {
757         sys->cpu->pr += 2;
758     }
759 }
760
761 /**
762  * JOV命令。語長2
763  * \relates exec
764  */
765 void jov()
766 {
767     WORD w[2];
768     w[0] = sys->memory[sys->cpu->pr];
769     w[1] = sys->memory[sys->cpu->pr + 1];
770     if((sys->cpu->fr & OF) > 0) {
771         sys->cpu->pr = get_adr_x(w[1], w[0]);
772     } else {
773         sys->cpu->pr += 2;
774     }
775 }
776
777 /**
778  * JUMP命令。語長2
779  * \relates exec
780  */
781 void jump()
782 {
783     WORD w[2];
784     w[0] = sys->memory[sys->cpu->pr];
785     w[1] = sys->memory[sys->cpu->pr + 1];
786     sys->cpu->pr = get_adr_x(w[1], w[0]);
787 }
788
789 /**
790  * PUSH命令。語長2
791  * \relates exec
792  */
793 void push()
794 {
795     WORD w[2];
796     w[0] = sys->memory[sys->cpu->pr];
797     w[1] = sys->memory[sys->cpu->pr + 1];
798     assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
799     sys->memory[--(sys->cpu->sp)] = get_adr_x(w[1], w[0]);
800     sys->cpu->pr += 2;
801 }
802
803 /**
804  * POP命令。語長1
805  * \relates exec
806  */
807 void pop()
808 {
809     assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
810     WORD w[1];
811     w[0] = sys->memory[sys->cpu->pr];
812     sys->cpu->gr[get_r_r1(w[0])] = sys->memory[(sys->cpu->sp)++];
813     sys->cpu->pr += 1;
814 }
815
816 /**
817  * CALL命令。語長2
818  * \relates exec
819  */
820 void call()
821 {
822     assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
823     WORD w[2];
824     w[0] = sys->memory[sys->cpu->pr];
825     w[1] = sys->memory[sys->cpu->pr + 1];
826     sys->memory[--(sys->cpu->sp)] = sys->cpu->pr + 1;
827     sys->cpu->pr = get_adr_x(w[1], w[0]);
828 }
829
830 /**
831  * RET命令。語長1(OPのみ)
832  * \relates exec
833  */
834 void ret()
835 {
836     assert(sys->cpu->sp <= sys->memsize);
837     if(sys->cpu->sp == sys->memsize) {
838         execptr->stop = true;
839     } else if(sys->cpu->sp < sys->memsize) {
840         sys->cpu->pr = sys->memory[(sys->cpu->sp)++] + 1;
841     }
842 }
843
844 /**
845  * SVC命令。語長2
846  * \relates exec
847  */
848 void svc()
849 {
850     WORD w[2];
851     w[0] = sys->memory[sys->cpu->pr];
852     w[1] = sys->memory[sys->cpu->pr + 1];
853     switch(get_adr_x(w[1], w[0]))
854     {
855     case 0x0:                   /* STOP */
856         execptr->stop = true;
857         break;
858     case 0x1:                   /* IN */
859         svcin();
860         break;
861     case 0x2:                   /* OUT */
862         svcout();
863         break;
864     }
865     sys->cpu->pr += 2;
866 }
867
868 /**
869  * 仮想マシンCOMET IIの実行
870  * \class exec
871  */
872 void exec()
873 {
874     clock_t clock_begin, clock_end;
875     void (*cmdptr)();
876
877     create_code_type();                             /* 命令のコードとタイプがキーのハッシュ表を作成 */
878     if(execmode.trace == true) {
879         fprintf(stdout, "\nExecuting machine codes\n");
880     }
881     /* 機械語の実行 */
882     for (sys->cpu->pr = execptr->start; ; ) {
883         clock_begin = clock();                     /* クロック周波数設定のため、実行開始時間を格納 */
884         if(execmode.dump || execmode.trace) {      /* traceまたはdumpオプション指定時、改行を出力 */
885             if(execmode.trace) {                   /* traceオプション指定時、レジスタを出力 */
886                 fprintf(stdout, "#%04X: Register::::\n", sys->cpu->pr);
887                 dspregister();
888             }
889             if(execmode.dump) {                    /* dumpオプション指定時、メモリを出力 */
890                 fprintf(stdout, "#%04X: Memory::::\n", sys->cpu->pr);
891                 dumpmemory();
892             }
893             fprintf(stdout, "\n");
894         }
895         /* プログラムレジスタとスタックポインタをチェック */
896         if(sys->cpu->pr >= sys->memsize || sys->cpu->sp > sys->memsize || sys->cpu->sp <= execptr->end) {
897             if(sys->cpu->pr >= sys->memsize) {
898                 setcerr(201, pr2str(sys->cpu->pr));        /* Program Register (PR) - memory overflow */
899             } else if(sys->cpu->sp <= execptr->end) {
900                 setcerr(202, pr2str(sys->cpu->pr));        /* Stack Pointer (SP) - stack overflow */
901             } else if(sys->cpu->sp > sys->memsize) {
902                 setcerr(203, pr2str(sys->cpu->pr));        /* Stack Pointer (SP) - stack underflow */
903             }
904             goto execfin;
905         }
906         /* コードから命令を取得 */
907         /* 取得できない場合はエラー終了 */
908         if((cmdptr = getcmdptr(sys->memory[sys->cpu->pr] & 0xFF00)) == NULL) {
909             setcerr(204, pr2str(sys->cpu->pr));            /* OP in word #1 - not command code */
910             goto execfin;
911         }
912         /* 命令の実行 */
913         (*cmdptr)();
914         /* エラー発生時はエラー終了 */
915         if(cerr->num > 0) {
916             goto execfin;
917         }
918         /* 終了フラグがtrueの場合は、正常終了 */
919         if(execptr->stop == true) {
920             break;
921         }
922         /* クロック周波数の設定 */
923         do {
924             clock_end = clock();
925         } while(clock_end - clock_begin < CLOCKS_PER_SEC / sys->clocks);
926     }
927 execfin:
928     free_code_type();                              /* 命令のコードとタイプがキーのハッシュ表を解放 */
929     if(cerr->num > 0) {
930         fprintf(stderr, "Execute error - %d: %s\n", cerr->num, cerr->msg);
931     }
932 }