Ubuntu 10.04 PPC版で判明した問題を修正
[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 static 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 /**
68  * 命令の名前とタイプからハッシュ値を生成する
69  */
70 unsigned hash_cmdtype(const char *cmd, CMDTYPE type)
71 {
72     HKEY *keys[2];
73     unsigned hashval;
74
75     /* 命令名を設定 */
76     keys[0] = malloc_chk(sizeof(HKEY), "hash_cmdtype.keys[0]");
77     keys[0]->type = CHARS;
78     keys[0]->val.s = strdup_chk(cmd, "keys[0].val.s");
79     /* 命令タイプを設定 */
80     keys[1] = malloc_chk(sizeof(HKEY), "hash_cmdtype.keys[1]");
81     keys[1]->type = INT;
82     keys[1]->val.i = (int)(type & 070);
83     /* ハッシュ値の計算 */
84     hashval = hash(2, keys, cmdtabsize);
85     free_chk(keys[0]->val.s, "keys[0].val.s");
86     free_chk(keys[0], "keys[0]");
87     free_chk(keys[1], "keys[1]");
88     /* ハッシュ値を返す */
89     return hashval;
90 }
91
92 /**
93  * 名前とタイプがキーの命令ハッシュ表を作成する
94  */
95 bool create_cmdtype_code()
96 {
97     CMDTAB *np;
98     unsigned hashval;
99     int i;
100
101     cmdtabsize = comet2cmdsize;
102     cmdtype_code = calloc_chk(cmdtabsize, sizeof(CMDTAB *), "cmdtype_code");
103     for(i = 0; i < cmdtabsize; i++) {
104         *(cmdtype_code + i) = NULL;
105     }
106     for(i = 0; i < comet2cmdsize; i++) {
107         np = malloc_chk(sizeof(CMDTAB), "cmdtype_code.np");
108         np->cmd = NULL;
109         np->next = NULL;
110         /* ハッシュ値の生成 */
111         hashval = hash_cmdtype(comet2cmd[i].name, comet2cmd[i].type);
112         /* ハッシュ表に値を追加 */
113         np->next = cmdtype_code[hashval];
114         cmdtype_code[hashval] = np;
115         np->cmd = &(comet2cmd[i]);
116     }
117     return true;
118 }
119
120 /**
121  * 命令の名前とタイプから、命令コードを返す
122  * 無効な場合は0xFFFFを返す
123  */
124 WORD getcmdcode(const char *cmd, CMDTYPE type)
125 {
126     CMDTAB *np;
127
128     assert(cmd != NULL);
129     for(np = cmdtype_code[hash_cmdtype(cmd, type)]; np != NULL; np = np->next){
130         if(strcmp(cmd, np->cmd->name) == 0 && type == np->cmd->type) {
131             return np->cmd->code;
132         }
133     }
134     return 0xFFFF;
135 }
136
137 /**
138  * 名前とタイプがキーの命令ハッシュ表を解放する
139  */
140 void free_cmdtype_code()
141 {
142     int i;
143     CMDTAB *np, *nq;
144
145     for(i = 0; i < cmdtabsize; i++) {
146         np = cmdtype_code[i];
147         while(np != NULL) {
148             nq = np->next;
149             free_chk(np, "free_cmdtype_code.np");
150             np = nq;
151         }
152     }
153     free_chk(cmdtype_code, "cmdtype_code");
154 }
155
156 /**
157  * 命令コードからハッシュ値を生成する
158  */
159 unsigned hash_code(WORD code)
160 {
161     HKEY *keys[1];
162
163     /* 命令コードを設定 */
164     keys[0] = malloc_chk(sizeof(HKEY), "hash_code.key");
165     keys[0]->type = INT;
166     keys[0]->val.i = (int)(code >> 8);
167     /* ハッシュ値を返す */
168     return hash(1, keys, cmdtabsize);
169 }
170
171 /**
172  * コードがキーの命令ハッシュ表を作成する
173  */
174 bool create_code_type()
175 {
176     CMDTAB *np;
177     unsigned hashval;
178     int i;
179
180     cmdtabsize = comet2cmdsize;
181     code_type = calloc_chk(cmdtabsize, sizeof(CMDTAB *), "code_type");
182     for(i = 0; i < cmdtabsize; i++) {
183         *(code_type + i) = NULL;
184     }
185     for(i = 0; i < comet2cmdsize; i++) {
186         np = malloc_chk(sizeof(CMDTAB), "code_type.np");
187         np->cmd = NULL;
188         np->next = NULL;
189         /* ハッシュ値の生成 */
190         hashval = hash_code((&comet2cmd[i])->code);
191         /* ハッシュ表に値を追加 */
192         np->next = code_type[hashval];
193         code_type[hashval] = np;
194         np->cmd = &comet2cmd[i];
195     }
196     return true;
197 }
198
199 /**
200  * 命令コードから命令タイプを返す
201  * 無効な場合はNONEを返す
202  */
203 CMDTYPE getcmdtype(WORD code)
204 {
205     CMDTAB *np;
206     for(np = code_type[hash_code(code)]; np != NULL; np = np->next) {
207         if(code == np->cmd->code) {
208             return np->cmd->type;
209         }
210     }
211     return NONE;
212 }
213
214 /**
215  * コードがキーの命令ハッシュ表を解放する
216  */
217 void free_code_type()
218 {
219     int i;
220     CMDTAB *np, *nq;
221     for(i = 0; i < cmdtabsize; i++) {
222         np = code_type[i];
223         while(np != NULL) {
224             nq = np->next;
225             free_chk(np, "code_type.np");
226             np = nq;
227         }
228     }
229     free_chk(code_type, "code_type");
230 }