fb9ae6fafe8315caf1cdffb6ddbcf50beb35ef03
[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 *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), "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
121     assert(cmd != NULL);
122     for(p = cmdtype_code[hash_cmdtype(cmd, type)]; p != NULL; p = p->next){
123         if(strcmp(cmd, p->cmd->name) == 0 && type == p->cmd->type) {
124             return p->cmd->code;
125         }
126     }
127     return 0xFFFF;
128 }
129
130 /**
131  * 名前とタイプがキーの命令ハッシュ表を解放する
132  */
133 void free_cmdtype_code()
134 {
135     int i;
136     CMDTAB *p, *q;
137
138     for(i = 0; i < cmdtabsize; i++) {
139         for(p = cmdtype_code[i]; p != NULL; p = q) {
140             q = p->next;
141             free_chk(p, "free_cmdtype_code.p");
142         }
143     }
144     free_chk(cmdtype_code, "cmdtype_code");
145 }
146
147 /**
148  * 命令コードからハッシュ値を生成する
149  */
150 unsigned hash_code(WORD code)
151 {
152     HKEY *keys[1];
153
154     /* 命令コードを設定 */
155     keys[0] = malloc_chk(sizeof(HKEY), "hash_code.key");
156     keys[0]->type = INT;
157     keys[0]->val.i = (int)(code >> 8);
158     /* ハッシュ値を返す */
159     return hash(1, keys, cmdtabsize);
160 }
161
162 /**
163  * コードがキーの命令ハッシュ表を作成する
164  */
165 bool create_code_type()
166 {
167     CMDTAB *p;
168     unsigned hashval;
169     int i;
170
171     cmdtabsize = comet2cmdsize;
172     code_type = calloc_chk(cmdtabsize, sizeof(CMDTAB *), "code_type");
173     for(i = 0; i < comet2cmdsize; i++) {
174         p = malloc_chk(sizeof(CMDTAB), "code_type.p");
175         hashval = hash_code((&comet2cmd[i])->code);    /* ハッシュ値の生成 */
176         p->next = code_type[hashval];    /* ハッシュ表に値を追加 */
177         p->cmd = &comet2cmd[i];
178         code_type[hashval] = p;
179     }
180     return true;
181 }
182
183 /**
184  * 命令コードから命令タイプを返す
185  * 無効な場合はNOTCMDを返す
186  */
187 CMDTYPE getcmdtype(WORD code)
188 {
189     CMDTAB *p;
190     for(p = code_type[hash_code(code)]; p != NULL; p = p->next) {
191         if(code == p->cmd->code) {
192             return p->cmd->type;
193         }
194     }
195     return NOTCMD;
196 }
197
198 /**
199  * コードがキーの命令ハッシュ表を解放する
200  */
201 void free_code_type()
202 {
203     int i;
204     CMDTAB *p, *q;
205     for(i = 0; i < cmdtabsize; i++) {
206         p = code_type[i];
207         while(p != NULL) {
208             q = p->next;
209             free_chk(p, "code_type.p");
210             p = q;
211         }
212     }
213     free_chk(code_type, "code_type");
214 }