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