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