命令のコードとタイプがキーのハッシュ表の名前を修正
[YACASL2.git] / src / struct.c
1 #include <stdio.h>
2 #include <assert.h>
3 #include <string.h>
4 #include "hash.h"
5 #include "struct.h"
6 #include "cmem.h"
7 #include "exec.h"
8
9 /**
10  * COMET IIの仮想実行マシンシステム
11  */
12 SYSTEM *sys;
13
14 /**
15  * プログラム実行時の開始と終了のアドレス
16  */
17 EXECPTR *execptr;
18
19 /**
20  * システムCOMET IIの命令表
21  */
22 static COMET2CMD comet2cmd[] = {
23     { "NOP", NONE, 0x0, nop },
24     { "LD", R_ADR_X, 0x1000, ld_r_adr_x },
25     { "ST", R_ADR_X, 0x1100, st },
26     { "LAD", R_ADR_X, 0x1200, lad },
27     { "LD", R1_R2, 0x1400, ld_r1_r2 },
28     { "ADDA", R_ADR_X, 0x2000, adda_r_adr_x },
29     { "SUBA", R_ADR_X, 0x2100, suba_r_adr_x },
30     { "ADDL", R_ADR_X, 0x2200, addl_r_adr_x },
31     { "SUBL", R_ADR_X, 0x2300, subl_r_adr_x },
32     { "ADDA", R1_R2, 0x2400, adda_r1_r2 },
33     { "SUBA", R1_R2, 0x2500, suba_r1_r2 },
34     { "ADDL", R1_R2, 0x2600, addl_r1_r2 },
35     { "SUBL", R1_R2, 0x2700, subl_r1_r2 },
36     { "AND", R_ADR_X, 0x3000, and_r_adr_x },
37     { "OR", R_ADR_X, 0x3100, or_r_adr_x },
38     { "XOR", R_ADR_X, 0x3200, xor_r_adr_x },
39     { "AND", R1_R2, 0x3400, and_r1_r2 },
40     { "OR", R1_R2, 0x3500, or_r1_r2 },
41     { "XOR", R1_R2, 0x3600, xor_r1_r2 },
42     { "CPA", R_ADR_X, 0x4000, cpa_r_adr_x },
43     { "CPL", R_ADR_X, 0x4100, cpl_r_adr_x },
44     { "CPA", R1_R2, 0x4400, cpa_r1_r2 },
45     { "CPL", R1_R2, 0x4500, cpl_r1_r2 },
46     { "SLA", R_ADR_X, 0x5000, sla },
47     { "SRA", R_ADR_X, 0x5100, sra },
48     { "SLL", R_ADR_X, 0x5200, sll },
49     { "SRL", R_ADR_X, 0x5300, srl },
50     { "JMI", ADR_X, 0x6100, jmi },
51     { "JNZ", ADR_X, 0x6200, jnz },
52     { "JZE", ADR_X, 0x6300, jze },
53     { "JUMP", ADR_X, 0x6400, jump },
54     { "JPL", ADR_X, 0x6500, jpl },
55     { "JOV", ADR_X, 0x6600, jov },
56     { "PUSH", ADR_X, 0x7000, push },
57     { "POP", R_, 0x7100, pop },
58     { "CALL", ADR_X, 0x8000, call },
59     { "SVC", ADR_X, 0xF000, svc },
60     { "RET", NONE, 0x8100, ret },
61 };
62
63 /**
64  * 命令表のサイズ
65  */
66 static int comet2cmdsize = ARRAYSIZE(comet2cmd);
67
68 /**
69  * ハッシュ表のサイズ
70  */
71 enum {
72     CMDTABSIZE = 39,
73 };
74
75 /**
76  * ハッシュ表
77  */
78 static CMDTAB *cmdtype_code[CMDTABSIZE], *code_cmdtype[CMDTABSIZE];
79
80 /**
81  * 命令の名前とタイプからハッシュ値を生成する
82  */
83 unsigned hash_cmdtype(const char *cmd, CMDTYPE type)
84 {
85     HKEY *keys[2];
86     unsigned hashval;
87
88     /* 命令名を設定 */
89     keys[0] = malloc_chk(sizeof(HKEY), "hash_cmdtype.keys[0]");
90     keys[0]->type = CHARS;
91     keys[0]->val.s = strdup_chk(cmd, "keys[0].val.s");
92     /* 命令タイプを設定 */
93     keys[1] = malloc_chk(sizeof(HKEY), "hash_cmdtype.keys[1]");
94     keys[1]->type = INT;
95     keys[1]->val.i = (int)(type & 070);
96     /* ハッシュ値の計算 */
97     hashval = hash(2, keys, CMDTABSIZE);
98     FREE(keys[0]->val.s);
99     FREE(keys[0]);
100     FREE(keys[1]);
101     /* ハッシュ値を返す */
102     return hashval;
103 }
104
105 /**
106  * 名前とタイプがキーの命令ハッシュ表を作成する
107  */
108 bool create_cmdtype_code()
109 {
110     CMDTAB *p;
111     unsigned hashval;
112     int i;
113
114     for(i = 0; i < comet2cmdsize; i++) {
115         hashval = hash_cmdtype(comet2cmd[i].name, comet2cmd[i].type);    /* ハッシュ値の生成 */
116         p = malloc_chk(sizeof(CMDTAB), "cmdtype_code");
117         p->cmd = &comet2cmd[i];
118         p->next = cmdtype_code[hashval];                                 /* ハッシュ表に値を追加 */
119         cmdtype_code[hashval] = p;
120     }
121     return true;
122 }
123
124 /**
125  * 命令の名前とタイプから、命令コードを返す\n
126  * 無効な場合は0xFFFFを返す
127  */
128 WORD getcmdcode(const char *cmd, CMDTYPE type)
129 {
130     CMDTAB *p;
131     WORD w = 0xFFFF;
132
133     assert(cmd != NULL);
134     for(p = cmdtype_code[hash_cmdtype(cmd, type)]; p != NULL; p = p->next) {
135         if(strcmp(cmd, p->cmd->name) == 0 && type == p->cmd->type) {
136             w = p->cmd->code;
137             break;
138         }
139     }
140     return w;
141 }
142
143 /**
144  * 名前とタイプがキーの命令ハッシュ表を解放する
145  */
146 void free_cmdtype_code()
147 {
148     int i;
149     CMDTAB *p, *q;
150
151     for(i = 0; i < CMDTABSIZE; i++) {
152         for(p = cmdtype_code[i]; p != NULL; p = q) {
153             q = p->next;
154             FREE(p);
155         }
156     }
157 }
158
159 /**
160  * 命令コードからハッシュ値を生成する
161  */
162 unsigned hash_code(WORD code)
163 {
164     HKEY *keys[1];
165     unsigned h;
166
167     /* 命令コードを設定 */
168     keys[0] = malloc_chk(sizeof(HKEY), "hash_code.key");
169     keys[0]->type = INT;
170     keys[0]->val.i = (int)(code >> 8);
171     h = hash(1, keys, CMDTABSIZE);
172     FREE(keys[0]);
173     return h;
174 }
175
176 /**
177  * コードがキーの命令ハッシュ表を作成する
178  */
179 bool create_code_cmdtype()
180 {
181     CMDTAB *p;
182     unsigned hashval;
183     int i;
184
185     for(i = 0; i < comet2cmdsize; i++) {
186         hashval = hash_code((&comet2cmd[i])->code);    /* ハッシュ値の生成 */
187         p = malloc_chk(sizeof(CMDTAB), "code_cmdtype");
188         p->cmd = &comet2cmd[i];
189         p->next = code_cmdtype[hashval];                  /* ハッシュ表に値を追加 */
190         code_cmdtype[hashval] = p;
191     }
192     return true;
193 }
194
195 /**
196  * 命令コードから命令の関数ポインタを返す
197  */
198 const void (*getcmdptr(WORD code))
199 {
200     CMDTAB *t;
201     const void *ptr = NULL;
202
203     for(t = code_cmdtype[hash_code(code)]; t != NULL; t = t->next) {
204         if(code == t->cmd->code) {
205             ptr = t->cmd->ptr;
206             break;
207         }
208     }
209     return ptr;
210 }
211
212 /**
213  * 命令コードから命令の名前を返す
214  */
215 char (*getcmdname(WORD code))
216 {
217     CMDTAB *t;
218     char *cmd = NULL;
219
220     for(t = code_cmdtype[hash_code(code)]; t != NULL; t = t->next) {
221         if(code == t->cmd->code) {
222             cmd = t->cmd->name;
223             break;
224         }
225     }
226     return cmd;
227 }
228
229 /**
230  * コードがキーの命令ハッシュ表を解放する
231  */
232 void free_code_cmdtype()
233 {
234     int i;
235     CMDTAB *p, *q;
236     for(i = 0; i < CMDTABSIZE; i++) {
237         for(p = code_cmdtype[i]; p != NULL; p = q) {
238             q = p->next;
239             FREE(p);
240         }
241     }
242 }
243
244 /**
245  * COMET II仮想マシンのリセット
246  */
247 void reset(int memsize, int clocks)
248 {
249     int i;
250
251     sys = malloc_chk(sizeof(SYSTEM), "sys");
252     /* メモリサイズを設定 */
253     sys->memsize = memsize;
254     /* クロック周波数を設定 */
255     sys->clocks = clocks;
256     /* メモリを初期化 */
257     sys->memory = calloc_chk(sys->memsize, sizeof(WORD), "memory");
258     /* CPUを初期化 */
259     sys->cpu = malloc_chk(sizeof(CPU), "cpu");
260     for(i = 0; i < GRSIZE; i++) {                    /* 汎用レジスタ  */
261         sys->cpu->gr[i] = 0x0;
262     }
263     sys->cpu->sp = sys->memsize;   /* スタックポインタ */
264     sys->cpu->pr = 0x0;            /* プログラムレジスタ */
265     sys->cpu->fr = 0x0;            /* フラグレジスタ */
266     /* CASL2プログラムの開始と終了のアドレスを初期化 */
267     execptr = malloc_chk(sizeof(EXECPTR), "execptr");
268     execptr->stop = false;
269 }
270
271 /**
272  * COMET II仮想マシンのシャットダウン
273  */
274 void shutdown()
275 {
276     FREE(execptr);
277     FREE(sys->memory);
278     FREE(sys->cpu);
279     FREE(sys);
280 }