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