Valgrindで見つかったメモリー周辺の問題点を修正
[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(keys[0]->val.s);
86     FREE(keys[0]);
87     FREE(keys[1]);
88     /* ハッシュ値を返す */
89     return hashval;
90 }
91
92 /**
93  * 名前とタイプがキーの命令ハッシュ表を作成する
94  */
95 bool create_cmdtype_code()
96 {
97     CMDTAB *p;
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 < comet2cmdsize; i++) {
104         p = malloc_chk(sizeof(CMDTAB), "create_cmdtype_code.p");
105         hashval = hash_cmdtype(comet2cmd[i].name, comet2cmd[i].type);    /* ハッシュ値の生成 */
106         p->next = cmdtype_code[hashval];                                 /* ハッシュ表に値を追加 */
107         p->cmd = &comet2cmd[i];
108         cmdtype_code[hashval] = p;
109     }
110     return true;
111 }
112
113 /**
114  * 命令の名前とタイプから、命令コードを返す
115  * 無効な場合は0xFFFFを返す
116  */
117 WORD getcmdcode(const char *cmd, CMDTYPE type)
118 {
119     CMDTAB *p;
120     WORD w = 0xFFFF;
121
122     assert(cmd != NULL);
123     for(p = cmdtype_code[hash_cmdtype(cmd, type)]; p != NULL; p = p->next) {
124         if(strcmp(cmd, p->cmd->name) == 0 && type == p->cmd->type) {
125             w = p->cmd->code;
126             break;
127         }
128     }
129     return w;
130 }
131
132 /**
133  * 名前とタイプがキーの命令ハッシュ表を解放する
134  */
135 void free_cmdtype_code()
136 {
137     int i;
138     CMDTAB *p, *q;
139
140     for(i = 0; i < cmdtabsize; i++) {
141         for(p = cmdtype_code[i]; p != NULL; p = q) {
142             q = p->next;
143             FREE(p);
144         }
145     }
146 }
147
148 /**
149  * 命令コードからハッシュ値を生成する
150  */
151 unsigned hash_code(WORD code)
152 {
153     HKEY *keys[1];
154     unsigned h;
155
156     /* 命令コードを設定 */
157     keys[0] = malloc_chk(sizeof(HKEY), "hash_code.key");
158     keys[0]->type = INT;
159     keys[0]->val.i = (int)(code >> 8);
160     h = hash(1, keys, cmdtabsize);
161     FREE(keys[0]);
162     return h;
163 }
164
165 /**
166  * コードがキーの命令ハッシュ表を作成する
167  */
168 bool create_code_type()
169 {
170     CMDTAB *p;
171     unsigned hashval;
172     int i;
173
174     cmdtabsize = comet2cmdsize;                    /* ハッシュ表のサイズ */
175     code_type = calloc_chk(comet2cmdsize, sizeof(CMDTAB *), "code_type");
176     for(i = 0; i < comet2cmdsize; i++) {
177         p = malloc_chk(sizeof(CMDTAB), "code_type.p");
178         hashval = hash_code((&comet2cmd[i])->code);    /* ハッシュ値の生成 */
179         p->next = code_type[hashval];                  /* ハッシュ表に値を追加 */
180         p->cmd = &comet2cmd[i];
181         code_type[hashval] = p;
182     }
183     return true;
184 }
185
186 /**
187  * 命令コードから命令タイプを返す
188  * 無効な場合はNOTCMDを返す
189  */
190 CMDTYPE getcmdtype(WORD code)
191 {
192     CMDTAB *p;
193     CMDTYPE t = NOTCMD;
194
195     for(p = code_type[hash_code(code)]; p != NULL; p = p->next) {
196         if(code == p->cmd->code) {
197             t = p->cmd->type;
198             break;
199         }
200     }
201     return t;
202 }
203
204 /**
205  * コードがキーの命令ハッシュ表を解放する
206  */
207 void free_code_type()
208 {
209     int i;
210     CMDTAB *p, *q;
211     for(i = 0; i < cmdtabsize; i++) {
212         for(p = code_type[i]; p != NULL; p = q) {
213             q = p->next;
214             FREE(p);
215         }
216     }
217 }