SLAのオーバーフロー時の動作を修正
[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     WORD w;
34
35     for(i = 0; i < memory[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((w = memory[GR[1]+i]) == '\0') {
41             break;
42         }
43         /* 「文字の組」の符号表に記載された文字と、改行(CR)/タブを表示 */
44         /* それ以外の文字は、「.」で表す */
45         if((w >= 0x20 && w <= 0x7E) || w == 0xA || w == '\t') {
46             putchar((char)w);
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     WORD sign, res, last;
143     int i;
144
145     FR = 0x0;
146     sign = val0 & 0x8000;
147     res = val0 & 0x7FFF;
148     for(i = 0; i < val1; i++) {
149         last = res & 0x4000;
150         res <<= 1;
151     }
152     res = sign | (res & 0x7F);
153     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
154     if(last > 0x0) {
155         FR += OF;
156     }
157     /* 符号(第15ビット)が1のとき、SFは1 */
158     if(sign > 0x0) {
159         FR += SF;
160     }
161     /* 演算結果が0のとき、ZFは1 */
162     if(res == 0x0) {
163         FR += ZF;
164     }
165     return res;
166 }
167
168 /* 算術右シフト。フラグを設定して値を返す */
169 /* 算術演算なので、第15ビットは送り出されない */
170 /* 空いたビット位置には符号と同じものが入る */
171 WORD sra(WORD val0, WORD val1)
172 {
173     WORD sign, res, last;
174     int i;
175
176     FR = 0x0;
177     sign = val0 & 0x8000;
178     res = val0 & 0x7FFF;
179     for(i = 0; i < val1; i++) {
180         last = res & 0x1;
181         res >>= 1;
182         if(sign > 0) {
183             res |= 0x4000;
184         }
185     }
186     res = sign | res;
187     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
188     if(last > 0x0) {
189         FR += OF;
190     }
191     /* 符号(第15ビット)が1のとき、SFは1 */
192     if(sign > 0x0) {
193         FR += SF;
194     }
195     /* 演算結果が0のとき、ZFは1 */
196     if(res == 0x0) {
197         FR += ZF;
198     }
199     return res;
200 }
201
202 /* 論理左シフト。フラグを設定して値を返す */
203 WORD sll(WORD val0, WORD val1)
204 {
205     WORD res = val0, last;
206     int i;
207
208     FR = 0x0;
209     for(i = 0; i < val1; i++) {
210         last = res & 0x8000;
211         res <<= 1;
212     }
213     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
214     if(last > 0x0) {
215         FR += OF;
216     }
217     /* 第15ビットが1のとき、SFは1 */
218     if((res & 0x8000) > 0x0) {
219         FR += SF;
220     }
221     /* 演算結果が0のとき、ZFは1 */
222     if(res == 0x0) {
223         FR += ZF;
224     }
225     return res;
226 }
227
228 /* 論理右シフト。フラグを設定して値を返す */
229 WORD srl(WORD val0, WORD val1)
230 {
231     WORD res = val0, last;
232     int i;
233
234     FR = 0x0;
235     for(i = 0; i < val1; i++) {
236         last = res & 0x0001;
237         res >>= 1;
238     }
239     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
240     if(last > 0x0) {
241         FR += OF;
242     }
243     /* 第15ビットが1のとき、SFは1 */
244     if((res & 0x8000) > 0x0) {
245         FR += SF;
246     }
247     /* 演算結果が0のとき、ZFは1 */
248     if(res == 0x0) {
249         FR += ZF;
250     }
251     return res;
252 }
253
254 /* COMET II仮想マシンのリセット */
255 void reset()
256 {
257     int i;
258     for(i = 0; i < REGSIZE; i++) {
259         GR[i] = 0x0;
260     }
261     SP = PR = FR = 0x0;
262     memory = malloc(memsize);
263     for(i = 0; i < memsize; i++) {
264         memory[i] = 0x0;
265     }
266 }
267
268 /* コードの実行 */
269 void exec()
270 {
271     WORD op, r_r1, x_r2, val;
272     CMDTYPE cmdtype;
273     char *errpr = malloc(8);
274     clock_t clock_begin, clock_end;
275
276     if((&execmode)->trace) {
277         fprintf(stdout, "\nExecuting machine codes\n");
278     }
279     /* フラグレジスタの初期値設定 */
280     FR = 0x0;
281     SP = memsize;
282     PR = startptr;
283     if(create_code_type() == false) {
284         goto execerr;
285     }
286     /* 機械語の実行 */
287     for (; ; ) {
288         clock_begin = clock();
289         /* プログラムレジスタのアドレスが主記憶の範囲外の場合はエラー */
290         if(PR >= memsize) {
291             sprintf(errpr, "PR:#%04X", PR);
292             setcerr(204, errpr);    /* Program Register (PR) - out of COMET II memory */
293         }
294         /* スタック領域のアドレスが主記憶の範囲外の場合はエラー */
295         if(SP > memsize) {
296             sprintf(errpr, "PR:#%04X", PR);
297             setcerr(207, errpr);    /* Stack Pointer (SP) - out of COMET II memory */
298         }
299         /* スタック領域を確保できない場合はエラー */
300         if(SP <= endptr) {
301             sprintf(errpr, "PR:#%04X", PR);
302             setcerr(205, errpr);    /* Stack Pointer (SP) - cannot allocate stack buffer */
303         }
304         op = memory[PR] & 0xFF00;
305         cmdtype = getcmdtype(op);
306         r_r1 = (memory[PR] >> 4) & 0xF;
307         x_r2 = memory[PR] & 0xF;
308         /* エラー発生時は終了 */
309         if(cerrno > 0) {
310             goto execerr;
311         }
312         if((&execmode)->trace){
313             fprintf(stdout, "#%04X: Register::::\n", PR);
314             dspregister();
315         }
316         if((&execmode)->dump){
317             fprintf(stdout, "#%04X: Memory::::\n", PR);
318             dumpmemory();
319         }
320         if((&execmode)->dump || (&execmode)->trace) {
321             fprintf(stdout, "\n");
322         }
323         PR++;
324         /* 処理対象の値を取得 */
325         if(cmdtype == R1_R2) {
326             assert(x_r2 < REGSIZE);
327             val = GR[x_r2];
328         }
329         else if(cmdtype ==  R_ADR_X || cmdtype == R_ADR_X_ || cmdtype == ADR_X) {
330             /* 実効アドレス(値または値が示す番地)を取得  */
331             val = memory[PR++];
332             /* 指標アドレスを加算  */
333             if(x_r2 > 0x0) {
334                 val += GR[x_r2];
335             }
336             /* ロード/算術論理演算命令/比較演算命令では、アドレスに格納されている内容を取得 */
337             if(cmdtype == R_ADR_X_) {
338                 if(val >= memsize) {
339                     sprintf(errpr, "PR:#%04X", PR-1);
340                     setcerr(206, errpr);    /* Address - out of COMET II memory */
341                     goto execerr;
342                 }
343                 val = memory[val];
344             }
345         }
346         /* 主オペランドが1〜4の場合、第2ビットを無視 */
347         if(op >= 0x1000 && op <= 0x4FFF) {
348             op &= 0xFB00;
349         }
350         /* 命令ごとの処理を実行 */
351         switch(op)
352         {
353         case 0x0:  /* NOP */
354             break;
355         case 0x1000:    /* LD */
356             setfr(GR[r_r1] = val);
357             break;
358         case 0x1100:    /* ST */
359             memory[val] = GR[r_r1];
360             break;
361         case 0x1200:    /* LAD */
362             GR[r_r1] = val;
363             break;
364         case 0x2000:  /* ADDA */
365             GR[r_r1] = adda(GR[r_r1], val);
366             break;
367         case 0x2100:  /* SUBA */
368             GR[r_r1] = suba(GR[r_r1], val);
369             break;
370         case 0x2200:  /* ADDL */
371             GR[r_r1] = addl(GR[r_r1], val);
372             break;
373         case 0x2300:  /* SUBL */
374             GR[r_r1] = subl(GR[r_r1], val);
375             break;
376         case 0x3000:  /* AND */
377             setfr(GR[r_r1] &= val);
378             break;
379         case 0x3100:  /* OR */
380             setfr(GR[r_r1] |= val);
381             break;
382         case 0x3200:  /* XOR */
383             setfr(GR[r_r1] ^= val);
384             break;
385         case 0x4000:  /* CPA */
386             cpa(GR[r_r1], val);
387             break;
388         case 0x4100:  /* CPL */
389             cpl(GR[r_r1], val);
390             break;
391         case 0x5000:  /* SLA */
392             GR[r_r1] = sla(GR[r_r1], val);
393             break;
394         case 0x5100:  /* SRA */
395             GR[r_r1] = sra(GR[r_r1], val);
396             break;
397         case 0x5200:  /* SLL */
398             GR[r_r1] = sll(GR[r_r1], val);
399             break;
400         case 0x5300:  /* SRL */
401             GR[r_r1] = srl(GR[r_r1], val);
402             break;
403         case 0x6100:  /* JMI */
404             if((FR & SF) > 0) {
405                 PR = val;
406             }
407             break;
408         case 0x6200:  /* JNZ */
409             if((FR & ZF) == 0) {
410                 PR = val;
411             }
412             break;
413         case 0x6300:  /* JZE */
414             if((FR & ZF) > 0) {
415                 PR = val;
416             }
417             break;
418         case 0x6400:  /* JUMP */
419             PR = val;
420             break;
421         case 0x6500:  /* JPL */
422             if((FR & (SF | ZF)) == 0) {
423                 PR = val;
424             }
425             break;
426         case 0x6600:  /* JOV */
427             if((FR & OF) > 0) {
428                 PR = val;
429             }
430             break;
431         case 0x7000:  /* PUSH */
432             assert(SP > endptr && SP <= memsize);
433             memory[--SP] = val;
434             break;
435         case 0x7100:  /* POP */
436             assert(SP > endptr && SP <= memsize);
437             GR[r_r1] = memory[SP++];
438             break;
439         case 0x8000:  /* CALL */
440             assert(SP > endptr && SP <= memsize);
441             memory[--SP] = PR;
442             PR = val;
443             break;
444         case 0x8100:  /* RET */
445             assert(SP > endptr && SP <= memsize);
446             if(SP == memsize) {
447                 return;
448             } else {
449                 PR = memory[SP++];
450                 break;
451             }
452         case 0xf000:  /* SVC */
453             switch(val)
454             {
455             case 0x0: /* EXIT */
456                 return;
457             case 0x1: /* IN */
458                 svcin();
459                 break;
460             case 0x2: /* OUT */
461                 svcout();
462                 break;
463             }
464         default:
465             break;
466         }
467         do {
468             clock_end = clock();
469         } while(clock_end - clock_begin < CLOCKS_PER_SEC / clocks);
470 /*        printf("PR:%04X; time: %f\n", PR, (double)((clock_end - clock_begin) * CLOCKS_PER_SEC)); */
471     }
472 execerr:
473     fprintf(stderr, "Execute error - %d: %s\n", cerrno, cerrmsg);
474 }