エラー表をコマンドごとに持つよう内部構造を変更
[YACASL2.git] / src / exec.c
1 #include "casl2.h"
2 #include "exec.h"
3
4 /* 標準入力から文字データを読込(SVC 1) */
5 void svcin()
6 {
7     int i;
8     char *buffer = malloc(INSIZE + 1);
9
10     if(fgets(buffer, INSIZE, stdin) == NULL) {
11         memory[GR[1]] = 0x0;
12         memory[GR[2]] = 0x0;
13         return;
14     }
15     for(i = 0; i < GR[1] && i < INSIZE; i++) {
16         if(*(buffer + i) == '\0' || *(buffer + i) == '\n') {
17             --i;
18             break;
19         }
20         if(GR[1] + i >= memsize - 1) {
21             setcerr(202, NULL);    /* SVC input - out of Input memory */
22             break;
23         }
24         memory[GR[1]+i] = *(buffer + i);
25     }
26     memory[GR[2]] = i + 1;
27 }
28
29 /* 標準出力へ文字データを書出(SVC 2) */
30 void svcout()
31 {
32     int i;
33     char c;
34
35     for(i = 0; i < GR[2]; i++) {
36         if(GR[1] + i >= memsize - 1) {
37             setcerr(203, NULL);    /* SVC output - out of Comet II memory */
38             return;
39         }
40         if(memory[GR[1]+i] == '\0') {
41             break;
42         }
43         /* 「文字の組」の符号表に記載された文字と、改行(CR)/タブを表示 */
44         /* それ以外の文字は、「.」で表す */
45         if(((c = (char)(memory[GR[1]+i])) >= 0x20 && c <= 0x7E) || c == 0xA || c == '\t') {
46             putchar(c);
47         } else {
48             putchar('.');
49         }
50     }
51 }
52
53 /* ロード/論理積/論理和/排他的論理和のフラグ設定。OFは常に0 */
54 void setfr(WORD val)
55 {
56     FR = 0x0;
57     /* 第15ビットが1のとき、SFは1 */
58     if((val & 0x8000) > 0x0) {
59         FR += SF;
60     }
61     /* 演算結果が0のとき、ZFは1 */
62     if(val == 0x0) {
63         FR += ZF;
64     }
65 }
66
67 /* 算術加算。フラグを設定して値を返す */
68 WORD adda(WORD val0, WORD val1)
69 {
70     WORD res;
71     long temp;
72     FR = 0x0;
73
74     temp = (signed short)val0 + (signed short)val1;
75     if(temp > 32767 || temp < -32768) {
76         FR += OF;
77     }
78     if(((res = (WORD)(temp & 0xFFFF)) & 0x8000) == 0x8000) {
79         FR += SF;
80     } else if(res == 0x0) {
81         FR += ZF;
82     }
83     return res;
84 }
85
86 /* 算術減算。フラグを設定して値を返す */
87 WORD suba(WORD val0, WORD val1)
88 {
89     return adda(val0, (~val1 + 1));
90 }
91
92 /* 論理加算。フラグを設定して値を返す */
93 WORD addl(WORD val0, WORD val1)
94 {
95     long temp;
96     WORD res;
97     FR = 0x0;
98
99     if((temp = val0 + val1) < 0 || temp > 65535) {
100         FR += OF;
101     }
102     if(((res = (WORD)(temp & 0xFFFF)) & 0x8000) == 0x8000) {
103         FR += SF;
104     } else if(res == 0x0) {
105         FR += ZF;
106     }
107     return res;
108 }
109
110 /* 論理減算。フラグを設定して値を返す */
111 WORD subl(WORD val0, WORD val1)
112 {
113     return addl(val0, (~val1 + 1));
114 }
115
116 /* 算術比較のフラグ設定。OFは常に0 */
117 void cpa(WORD val0, WORD val1)
118 {
119     FR = 0x0;
120     if((short)val0 < (short)val1) {
121         FR = SF;
122     } else if(val0 == val1) {
123         FR = ZF;
124     }
125 }
126
127 /* 論理比較のフラグ設定。OFは常に0 */
128 void cpl(WORD val0, WORD val1)
129 {
130     FR = 0x0;
131     if(val0 < val1) {
132         FR = SF;
133     } else if(val0 == val1) {
134         FR = ZF;
135     }
136 }
137
138 /* 算術左シフト。フラグを設定して値を返す。 */
139 /* 算術演算なので、第15ビットは送り出されない */
140 WORD sla(WORD val0, WORD val1)
141 {
142     FR = 0x0;
143     WORD sign, res;
144     sign = val0 & 0x8000;
145     res = ((val0 << val1) & 0x7FFF) | sign;
146     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
147     if((val0 & (0x4000 >> (val1 - 1))) > 0x0) {
148         FR += OF;
149     }
150     /* 符号(第15ビット)が1のとき、SFは1 */
151     if(sign > 0x0) {
152         FR += SF;
153     }
154     /* 演算結果が0のとき、ZFは1 */
155     if(res == 0x0) {
156         FR += ZF;
157     }
158     return res;
159 }
160
161 /* 算術右シフト。フラグを設定して値を返す */
162 WORD sra(WORD val0, WORD val1)
163 {
164     WORD sign, res, onbit = 0x8000;
165     int i;
166     FR = 0x0;
167     res = (val0 & 0x7FFF) >> val1;
168     /* 符号(第15ビット)が1の場合、符号と空いたビット位置に1を設定
169        COMET IIの仕様で、シフトの結果空いたビット位置には符号と同じものが入る */
170     if((sign = val0 & 0x8000) == 0x8000) {
171         for(i = 0; i <= val1; i++) {
172             res |= onbit;
173             onbit >>= 1;
174         }
175     }
176     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
177     if((val0 & (0x1 << (val1 - 1))) > 0x0) {
178         FR += OF;
179     }
180     /* 符号(第15ビット)が1のとき、SFは1 */
181     if(sign > 0x0) {
182         FR += SF;
183     }
184     /* 演算結果が0のとき、ZFは1 */
185     if(res == 0x0) {
186         FR += ZF;
187     }
188     return res;
189 }
190
191 /* 論理左シフト。フラグを設定して値を返す */
192 WORD sll(WORD val0, WORD val1)
193 {
194     FR = 0x0;
195     WORD res;
196     res = val0 << val1;
197     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
198     if((val0 & (0x8000 >> (val1 - 1))) > 0x0) {
199         FR += OF;
200     }
201     /* 第15ビットが1のとき、SFは1 */
202     if((res & 0x8000) > 0x0) {
203         FR += SF;
204     }
205     /* 演算結果が0のとき、ZFは1 */
206     if(res == 0x0) {
207         FR += ZF;
208     }
209     return res;
210 }
211
212 /* 論理右シフト。フラグを設定して値を返す */
213 WORD srl(WORD val0, WORD val1)
214 {
215     FR = 0x0;
216     WORD res;
217     res = val0 >> val1;
218     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
219     if((val0 & (0x1 << (val1 - 1))) > 0x0) {
220         FR += OF;
221     }
222     /* 第15ビットが1のとき、SFは1 */
223     if((res & 0x8000) == 0x8000) {
224         FR += SF;
225     }
226     /* 演算結果が0のとき、ZFは1 */
227     if(res == 0x0) {
228         FR += ZF;
229     }
230     return res;
231 }
232
233 /* COMET II仮想マシンのリセット */
234 void reset()
235 {
236     int i;
237     for(i = 0; i < REGSIZE; i++) {
238         GR[i] = 0x0;
239     }
240     SP = PR = FR = 0x0;
241     memory = malloc(memsize);
242     for(i = 0; i < memsize; i++) {
243         memory[i] = 0x0;
244     }
245 }
246
247 /* コードの実行 */
248 void exec()
249 {
250     WORD op, r_r1, x_r2, val;
251     CMDTYPE cmdtype;
252     char *errpr = malloc(8);
253     clock_t clock_begin, clock_end;
254
255     if((&execmode)->tracemode) {
256         fprintf(stdout, "\nExecuting machine codes\n");
257     }
258     /* フラグレジスタの初期値設定 */
259     FR = 0x0;
260     SP = memsize;
261     PR = startptr;
262     if(create_code_type() == false) {
263         goto execerr;
264     }
265     /* 機械語の実行 */
266     for (; ; ) {
267         clock_begin = clock();
268         /* プログラムレジスタのアドレスが主記憶の範囲外の場合はエラー */
269         if(PR >= memsize) {
270             sprintf(errpr, "PR:#%04X", PR);
271             setcerr(204, errpr);    /* Program Register (PR) - out of COMET II memory */
272         }
273         /* スタック領域のアドレスが主記憶の範囲外の場合はエラー */
274         if(SP > memsize) {
275             sprintf(errpr, "PR:#%04X", PR);
276             setcerr(207, errpr);    /* Stack Pointer (SP) - out of COMET II memory */
277         }
278         /* スタック領域を確保できない場合はエラー */
279         if(SP <= endptr) {
280             sprintf(errpr, "PR:#%04X", PR);
281             setcerr(205, errpr);    /* Stack Pointer (SP) - cannot allocate stack buffer */
282         }
283         op = memory[PR] & 0xFF00;
284         cmdtype = getcmdtype(op);
285         r_r1 = (memory[PR] >> 4) & 0xF;
286         x_r2 = memory[PR] & 0xF;
287         /* エラー発生時は終了 */
288         if(cerrno > 0) {
289             goto execerr;
290         }
291         if((&execmode)->tracemode){
292             fprintf(stdout, "#%04X: Register::::\n", PR);
293             dspregister();
294         }
295         if((&execmode)->dumpmode){
296             fprintf(stdout, "#%04X: Memory::::\n", PR);
297             dumpmemory();
298         }
299         if((&execmode)->dumpmode || (&execmode)->tracemode) {
300             fprintf(stdout, "\n");
301         }
302         PR++;
303         /* 処理対象の値を取得 */
304         if(cmdtype == R1_R2) {
305             assert(x_r2 < REGSIZE);
306             val = GR[x_r2];
307         }
308         else if(cmdtype ==  R_ADR_X || cmdtype == R_ADR_X_ || cmdtype == ADR_X) {
309             /* 実効アドレス(値または値が示す番地)を取得  */
310             val = memory[PR++];
311             /* 指標アドレスを加算  */
312             if(x_r2 > 0x0) {
313                 val += GR[x_r2];
314             }
315             /* ロード/算術論理演算命令/比較演算命令では、アドレスに格納されている内容を取得 */
316             if(cmdtype == R_ADR_X_) {
317                 if(val >= memsize) {
318                     sprintf(errpr, "PR:#%04X", PR-1);
319                     setcerr(206, errpr);    /* Address - out of COMET II memory */
320                     goto execerr;
321                 }
322                 val = memory[val];
323             }
324         }
325         /* 主オペランドが1〜4の場合、第2ビットを無視 */
326         if(op >= 0x1000 && op <= 0x4FFF) {
327             op &= 0xFB00;
328         }
329         /* 命令ごとの処理を実行 */
330         switch(op)
331         {
332         case 0x0:  /* NOP */
333             break;
334         case 0x1000:    /* LD */
335             setfr(GR[r_r1] = val);
336             break;
337         case 0x1100:    /* ST */
338             memory[val] = GR[r_r1];
339             break;
340         case 0x1200:    /* LAD */
341             GR[r_r1] = val;
342             break;
343         case 0x2000:  /* ADDA */
344             GR[r_r1] = adda(GR[r_r1], val);
345             break;
346         case 0x2100:  /* SUBA */
347             GR[r_r1] = suba(GR[r_r1], val);
348             break;
349         case 0x2200:  /* ADDL */
350             GR[r_r1] = addl(GR[r_r1], val);
351             break;
352         case 0x2300:  /* SUBL */
353             GR[r_r1] = subl(GR[r_r1], val);
354             break;
355         case 0x3000:  /* AND */
356             setfr(GR[r_r1] &= val);
357             break;
358         case 0x3100:  /* OR */
359             setfr(GR[r_r1] |= val);
360             break;
361         case 0x3200:  /* XOR */
362             setfr(GR[r_r1] ^= val);
363             break;
364         case 0x4000:  /* CPA */
365             cpa(GR[r_r1], val);
366             break;
367         case 0x4100:  /* CPL */
368             cpl(GR[r_r1], val);
369             break;
370         case 0x5000:  /* SLA */
371             GR[r_r1] = sla(GR[r_r1], val);
372             break;
373         case 0x5100:  /* SRA */
374             GR[r_r1] = sra(GR[r_r1], val);
375             break;
376         case 0x5200:  /* SLL */
377             GR[r_r1] = sll(GR[r_r1], val);
378             break;
379         case 0x5300:  /* SRL */
380             GR[r_r1] = srl(GR[r_r1], val);
381             break;
382         case 0x6100:  /* JMI */
383             if((FR & SF) > 0) {
384                 PR = val;
385             }
386             break;
387         case 0x6200:  /* JNZ */
388             if((FR & ZF) == 0) {
389                 PR = val;
390             }
391             break;
392         case 0x6300:  /* JZE */
393             if((FR & ZF) > 0) {
394                 PR = val;
395             }
396             break;
397         case 0x6400:  /* JUMP */
398             PR = val;
399             break;
400         case 0x6500:  /* JPL */
401             if((FR & (SF | ZF)) == 0) {
402                 PR = val;
403             }
404             break;
405         case 0x6600:  /* JOV */
406             if((FR & OF) > 0) {
407                 PR = val;
408             }
409             break;
410         case 0x7000:  /* PUSH */
411             assert(SP > endptr && SP <= memsize);
412             memory[--SP] = val;
413             break;
414         case 0x7100:  /* POP */
415             assert(SP > endptr && SP <= memsize);
416             GR[r_r1] = memory[SP++];
417             break;
418         case 0x8000:  /* CALL */
419             assert(SP > endptr && SP <= memsize);
420             memory[--SP] = PR;
421             PR = val;
422             break;
423         case 0x8100:  /* RET */
424             assert(SP > endptr && SP <= memsize);
425             if(SP == memsize) {
426                 return;
427             } else {
428                 PR = memory[SP++];
429                 break;
430             }
431         case 0xf000:  /* SVC */
432             switch(val)
433             {
434             case 0x0: /* EXIT */
435                 return;
436             case 0x1: /* IN */
437                 svcin();
438                 break;
439             case 0x2: /* OUT */
440                 svcout();
441                 break;
442             }
443         default:
444             break;
445         }
446         do {
447             clock_end = clock();
448         } while(clock_end - clock_begin < CLOCKS_PER_SEC / clocks);
449 /*        printf("PR:%04X; time: %f\n", PR, (double)((clock_end - clock_begin) * CLOCKS_PER_SEC)); */
450     }
451 execerr:
452     fprintf(stderr, "Execute error - %d: %s\n", cerrno, cerrmsg);
453 }