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