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