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