ソースの書き方を変更
[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), "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_chk(p, "free_cmdtype_code");
144         }
145     }
146 }
147
148 /**
149  * 命令コードからハッシュ値を生成する
150  */
151 unsigned hash_code(WORD code)
152 {
153     HKEY *keys[1];
154
155     /* 命令コードを設定 */
156     keys[0] = malloc_chk(sizeof(HKEY), "hash_code.key");
157     keys[0]->type = INT;
158     keys[0]->val.i = (int)(code >> 8);
159     /* ハッシュ値を返す */
160     return hash(1, keys, cmdtabsize);
161 }
162
163 /**
164  * コードがキーの命令ハッシュ表を作成する
165  */
166 bool create_code_type()
167 {
168     CMDTAB *p;
169     unsigned hashval;
170     int i;
171
172     cmdtabsize = comet2cmdsize;                    /* ハッシュ表のサイズ */
173     code_type = calloc_chk(comet2cmdsize, sizeof(CMDTAB *), "code_type");
174     for(i = 0; i < comet2cmdsize; i++) {
175         p = malloc_chk(sizeof(CMDTAB), "code_type.p");
176         hashval = hash_code((&comet2cmd[i])->code);    /* ハッシュ値の生成 */
177         p->next = code_type[hashval];                  /* ハッシュ表に値を追加 */
178         p->cmd = &comet2cmd[i];
179         code_type[hashval] = p;
180     }
181     return true;
182 }
183
184 /**
185  * 命令コードから命令タイプを返す
186  * 無効な場合はNOTCMDを返す
187  */
188 CMDTYPE getcmdtype(WORD code)
189 {
190     CMDTAB *p;
191     CMDTYPE t = NOTCMD;
192
193     for(p = code_type[hash_code(code)]; p != NULL; p = p->next) {
194         if(code == p->cmd->code) {
195             t = p->cmd->type;
196             break;
197         }
198     }
199     return t;
200 }
201
202 /**
203  * コードがキーの命令ハッシュ表を解放する
204  */
205 void free_code_type()
206 {
207     int i;
208     CMDTAB *p, *q;
209     for(i = 0; i < cmdtabsize; i++) {
210         for(p = code_type[i]; p != NULL; p = q) {
211             q = p->next;
212             free_chk(p, "code_type");
213         }
214     }
215 }