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