依存関係を整理
[YACASL2.git] / src / cmd.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
8 /**
9  * 機械語命令のリスト
10  */
11 CMD comet2cmd[] = {
12     { "NOP", NONE, 0x0 },
13     { "LD", R_ADR_X_, 0x1000 },
14     { "ST", R_ADR_X, 0x1100 },
15     { "LAD", R_ADR_X, 0x1200 },
16     { "LD", R1_R2, 0x1400 },
17     { "ADDA", R_ADR_X_, 0x2000 },
18     { "SUBA", R_ADR_X_, 0x2100 },
19     { "ADDL", R_ADR_X_, 0x2200 },
20     { "SUBL", R_ADR_X_, 0x2300 },
21     { "ADDA", R1_R2, 0x2400 },
22     { "SUBA", R1_R2, 0x2500 },
23     { "ADDL", R1_R2, 0x2600 },
24     { "SUBL", R1_R2, 0x2700 },
25     { "AND", R_ADR_X_, 0x3000 },
26     { "OR", R_ADR_X_, 0x3100 },
27     { "XOR", R_ADR_X_, 0x3200 },
28     { "AND", R1_R2, 0x3400 },
29     { "OR", R1_R2, 0x3500 },
30     { "XOR", R1_R2, 0x3600 },
31     { "CPA", R_ADR_X_, 0x4000 },
32     { "CPL", R_ADR_X_, 0x4100 },
33     { "CPA", R1_R2, 0x4400 },
34     { "CPL", R1_R2, 0x4500 },
35     { "SLA", R_ADR_X, 0x5000 },
36     { "SRA", R_ADR_X, 0x5100 },
37     { "SLL", R_ADR_X, 0x5200 },
38     { "SRL", R_ADR_X, 0x5300 },
39     { "JMI", ADR_X, 0x6100 },
40     { "JNZ", ADR_X, 0x6200 },
41     { "JZE", ADR_X, 0x6300 },
42     { "JUMP", ADR_X, 0x6400 },
43     { "JPL", ADR_X, 0x6500 },
44     { "JOV", ADR_X, 0x6600 },
45     { "PUSH", ADR_X, 0x7000 },
46     { "POP", R_, 0x7100 },
47     { "CALL", ADR_X, 0x8000 },
48     { "SVC", ADR_X, 0xF000 },
49     { "RET", NONE, 0x8100 },
50 };
51
52 /**
53  * 命令コード配列のサイズ
54  */
55 static int comet2cmdsize = ARRAYSIZE(comet2cmd);
56
57 /**
58  * 命令表のサイズ
59  */
60 static int cmdtabsize;
61
62 /**
63  * ハッシュ表
64  */
65 static CMDTAB **cmdtype_code, **code_type;
66
67 #ifndef UNITTEST
68 static unsigned hash_cmdtype(const char *cmd, CMDTYPE type);
69
70 static unsigned hash_code(WORD code);
71 #endif
72
73 /**
74  * 命令の名前とタイプからハッシュ値を生成する
75  */
76 unsigned hash_cmdtype(const char *cmd, CMDTYPE type)
77 {
78     HKEY *keys[2];
79     unsigned hashval;
80
81     /* 命令名を設定 */
82     keys[0] = malloc_chk(sizeof(HKEY), "hash_cmdtype.keys[0]");
83     keys[0]->type = CHARS;
84     keys[0]->val.s = strdup_chk(cmd, "keys[0].val.s");
85     /* 命令タイプを設定 */
86     keys[1] = malloc_chk(sizeof(HKEY), "hash_cmdtype.keys[1]");
87     keys[1]->type = INT;
88     keys[1]->val.i = (int)(type & 070);
89     /* ハッシュ値の計算 */
90     hashval = hash(2, keys, cmdtabsize);
91     free_chk(keys[0]->val.s, "keys[0].val.s");
92     free_chk(keys[0], "keys[0]");
93     free_chk(keys[1], "keys[1]");
94     /* ハッシュ値を返す */
95     return hashval;
96 }
97
98 /**
99  * 名前とタイプがキーの命令ハッシュ表を作成する
100  */
101 bool create_cmdtype_code()
102 {
103     CMDTAB *np;
104     unsigned hashval;
105     int i;
106
107     cmdtabsize = comet2cmdsize;
108     cmdtype_code = calloc_chk(cmdtabsize, sizeof(CMDTAB *), "cmdtype_code");
109     for(i = 0; i < cmdtabsize; i++) {
110         *(cmdtype_code + i) = NULL;
111     }
112     for(i = 0; i < comet2cmdsize; i++) {
113         np = malloc_chk(sizeof(CMDTAB), "cmdtype_code.next");
114         np->cmd = NULL;
115         np->next = NULL;
116         /* ハッシュ値の生成 */
117         hashval = hash_cmdtype(comet2cmd[i].name, comet2cmd[i].type);
118         /* ハッシュ表に値を追加 */
119         np->next = cmdtype_code[hashval];
120         cmdtype_code[hashval] = np;
121         np->cmd = &(comet2cmd[i]);
122     }
123     return true;
124 }
125
126 /**
127  * 命令の名前とタイプから、命令コードを返す
128  * 無効な場合は0xFFFFを返す
129  */
130 WORD getcmdcode(const char *cmd, CMDTYPE type)
131 {
132     CMDTAB *np;
133
134     assert(cmd != NULL);
135     for(np = cmdtype_code[hash_cmdtype(cmd, type)]; np != NULL; np = np->next){
136         if(strcmp(cmd, np->cmd->name) == 0 && type == np->cmd->type) {
137             return np->cmd->code;
138         }
139     }
140     return 0xFFFF;
141 }
142
143 /**
144  * 名前とタイプがキーの命令ハッシュ表を解放する
145  */
146 void free_cmdtype_code()
147 {
148     int i;
149     CMDTAB *np, *nq;
150
151     for(i = 0; i < cmdtabsize; i++) {
152         np = cmdtype_code[i];
153         while(np != NULL) {
154             nq = np->next;
155             free_chk(np, "free_cmdtype_code.np");
156             np = nq;
157         }
158     }
159     free_chk(cmdtype_code, "cmdtype_code");
160 }
161
162 /**
163  * 命令コードからハッシュ値を生成する
164  */
165 unsigned hash_code(WORD code)
166 {
167     HKEY *keys[1];
168
169     /* 命令コードを設定 */
170     keys[0] = malloc_chk(sizeof(HKEY), "hash_code.key");
171     keys[0]->type = INT;
172     keys[0]->val.i = (int)(code >> 8);
173     /* ハッシュ値を返す */
174     return hash(1, keys, cmdtabsize);
175 }
176
177 /**
178  * コードがキーの命令ハッシュ表を作成する
179  */
180 bool create_code_type()
181 {
182     CMDTAB *np;
183     unsigned hashval;
184     int i;
185
186     cmdtabsize = comet2cmdsize;
187     code_type = calloc_chk(cmdtabsize, sizeof(CMDTAB *), "code_type");
188     for(i = 0; i < cmdtabsize; i++) {
189         *(code_type + i) = NULL;
190     }
191     for(i = 0; i < comet2cmdsize; i++) {
192         np = malloc_chk(sizeof(CMDTAB), "code_type.next");
193         np->cmd = NULL;
194         np->next = NULL;
195         /* ハッシュ値の生成 */
196         hashval = hash_code((&comet2cmd[i])->code);
197         /* ハッシュ表に値を追加 */
198         np->next = code_type[hashval];
199         code_type[hashval] = np;
200         np->cmd = &comet2cmd[i];
201     }
202     return true;
203 }
204
205 /**
206  * 命令コードから命令タイプを返す
207  * 無効な場合はNONEを返す
208  */
209 CMDTYPE getcmdtype(WORD code)
210 {
211     CMDTAB *np;
212     for(np = code_type[hash_code(code)]; np != NULL; np = np->next) {
213         if(code == np->cmd->code) {
214             return np->cmd->type;
215         }
216     }
217     return NONE;
218 }
219
220 /**
221  * コードがキーの命令ハッシュ表を解放する
222  */
223 void free_code_type()
224 {
225     int i;
226     CMDTAB *np, *nq;
227     for(i = 0; i < cmdtabsize; i++) {
228         np = code_type[i];
229         while(np != NULL) {
230             nq = np->next;
231             free_chk(np, "np");
232             np = nq;
233         }
234     }
235     free_chk(code_type, "code_type");
236 }