Merge branch 'master'
[YACASL2.git] / src / disassemble.c
1 #include "disassemble.h"
2
3 /**
4  * @brief 機械コードの出力列
5  */
6 int codecol = 32;
7
8 /**
9  * @brief ファイルストリームから1ワードを取得する
10  *
11  * @return 取得した1ワード
12  *
13  * @param stream ファイルストリーム
14  */
15 WORD fgetword(FILE *stream);
16
17 /**
18  * @brief ファイルストリームを1ワード戻す
19  *
20  * @return なし
21  *
22  * @param stream ファイルストリーム
23  */
24 void fungetword(FILE *stream);
25
26 /**
27  * @brief ファイルストリームから、値が0の連続するWORD数を返す
28  *
29  * @return 値が0の連続するWORD数
30  *
31  * @param stream ファイルストリーム
32  */
33 WORD zero_data_cnt(FILE *stream);
34
35 /**
36  * @brief 機械コードをコメントとして標準出力へ出力する
37  *
38  * @return なし
39  *
40  * @param ascol アセンブラの列位置
41  * @param pradr 次に実行すべき命令語の先頭アドレス
42  * @param wordc ワード値の数
43  * @param wordv ワード値の配列
44  */
45 void disassemble_puts_code(int ascol, WORD pradr, int wordc, WORD wordv[]);
46
47 /**
48  * @brief 種類がR_ADRまたはR_ADR_Xのコマンドを逆アセンブルし、標準出力へ出力する
49  *
50  * @return なし
51  *
52  * @param cmdtype コマンドの種類
53  * @param *cmdname コマンドの名前
54  * @param word ワード値
55  * @param adr アドレス値
56  * @param pradr 次に実行すべき命令語の先頭アドレス
57  */
58 void disassemble_cmd_adr_x(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD adr, WORD pradr);
59
60 /**
61  * @brief 種類がR1_R2またはR_のコマンドを逆アセンブルし、標準出力へ出力する
62  *
63  * @return なし
64  *
65  * @param cmdtype コマンドの種類
66  * @param *cmdname コマンドの名前
67  * @param word ワード値
68  * @param pradr 次に実行すべき命令語の先頭アドレス
69  */
70 void disassemble_cmd_r(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD pradr);
71
72 /**
73  * @brief DCコマンドを逆アセンブルし、標準出力へ出力する
74  *
75  * @return なし
76  *
77  * @param word ワード値
78  * @param pradr 次に実行すべき命令語の先頭アドレス
79  */
80 void disassemble_dc(WORD word, WORD pradr);
81
82 void disassemble_puts_code(int ascol, WORD pradr, int wordc, WORD wordv[])
83 {
84     for(int i = 0; i < codecol-ascol; i++){
85         fprintf(stdout, " ");
86     }
87     if(wordc == 1) {
88         fprintf(stdout, "; #%04X: #%04X", pradr, wordv[0]);
89     } else if(wordc == 2) {
90         fprintf(stdout, "; #%04X: #%04X #%04X", pradr, wordv[0], wordv[1]);
91     }
92 }
93 void disassemble_cmd_adr_x(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD adr, WORD pradr)
94 {
95     WORD x = 0;
96     char *g = NULL;
97     int cnt = 0;
98
99     cnt += fprintf(stdout, "        %-7s ", cmdname);
100     if(cmdtype == R_ADR_X) {
101         cnt += fprintf(stdout, "%s,", g = grstr((word & 0x00F0) >> 4));
102         FREE(g);
103     }
104     cnt += fprintf(stdout, "#%04X", adr);
105     if((x = (word & 0x000F)) != 0) {
106         cnt += fprintf(stdout, ",%s", g = grstr(x));
107         FREE(g);
108     }
109     disassemble_puts_code(cnt, pradr, 2, (WORD []){word, adr});
110 }
111
112 void disassemble_cmd_r(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD pradr)
113 {
114     char *g = NULL;
115     char *g1 = NULL;
116     char *g2 = NULL;
117     int cnt = 0;
118
119     cnt += fprintf(stdout, "        %-7s ", cmdname);
120     if(cmdtype == R1_R2) {
121         g1 = grstr((word & 0x00F0) >> 4);
122         g2 = grstr(word & 0x000F);
123         cnt += fprintf(stdout, "%s,%s", g1, g2);
124         FREE(g1);
125         FREE(g2);
126     } else if(cmdtype == R_) {
127         g = grstr((word & 0x00F0) >> 4);
128         cnt += fprintf(stdout, "%s", g);
129         FREE(g);
130     }
131     disassemble_puts_code(cnt, pradr, 1, (WORD []){word});
132 }
133
134 void disassemble_dc(WORD word, WORD pradr)
135 {
136     int cnt = 0;
137
138     cnt = fprintf(stdout, "        DC      %-5d ", word);
139     disassemble_puts_code(cnt, pradr, 1, (WORD []){word});
140     fprintf(stdout, " ::" );
141     print_dumpword(word, true);
142 }
143
144 void disassemble_ds(WORD wcnt, WORD pradr)
145 {
146     int cnt = 0;
147
148     cnt = fprintf(stdout, "        DS      %-5d ", wcnt);
149     disassemble_puts_code(cnt, pradr, 1, (WORD []){0});
150     for(int i = 0; i < wcnt - 1; i++) {
151         fprintf(stdout, "\n");
152         disassemble_puts_code(0, pradr+1, 1, (WORD []){0});
153     }
154 }
155
156 WORD fgetword(FILE *stream)
157 {
158     WORD aword;
159     fread(&aword, sizeof(WORD), 1, stream);
160     return aword;
161 }
162
163 void fungetword(FILE *stream)
164 {
165     fseek(stream, -sizeof(WORD), SEEK_CUR);
166 }
167
168 WORD zero_data_cnt(FILE *stream)
169 {
170     WORD cnt = 0;
171     WORD word = 0;
172
173     while(!feof(stream) && word == 0) {
174         word = fgetword(stream);
175         cnt++;
176     }
177     if(!feof(stream)) {
178         fungetword(stream);
179     }
180     return cnt;
181 }
182
183 bool disassemble_file(const char *file)
184 {
185     bool stat = true;
186     FILE *fp = NULL;
187     WORD i = 0;
188     WORD word = 0;
189     WORD cmd = 0;
190     WORD zcnt = 0;
191     CMDTYPE cmdtype = 0;
192     const char *cmdname = NULL;
193     bool inst = true;
194
195     assert(file != NULL);
196     if((fp = fopen(file, "rb")) == NULL) {
197         perror(file);
198         return false;
199     }
200
201     create_cmdtable(HASH_CODE);                   /* 命令のコードとタイプがキーのハッシュ表を作成 */
202
203     fprintf(stdout, "MAIN    START\n");
204     for(word = fgetword(fp); !feof(fp); i++, word = fgetword(fp)) {
205         cmd = word & 0xFF00;
206         cmdname = getcmdname(cmd);
207         cmdtype = getcmdtype(cmd);
208         if(word == 0){
209             if(inst == true) {  /* プログラム領域の場合  */
210                 disassemble_cmd_r(NONE, "nop", 0, i);
211             } else {            /* データ領域の場合 */
212                 zcnt = zero_data_cnt(fp);
213                 if(zcnt == 1) { /* 1つだけの0はDCとみなす */
214                     disassemble_dc(0, i);
215                 } else {        /* 連続する0はDSとみなす */
216                     disassemble_ds(zcnt, i);
217                     i += zcnt - 1;
218                 }
219             }
220         } else if(cmd == 0) {
221             disassemble_dc(word, i);
222         } else {
223             if(cmdtype == R_ADR_X || cmdtype == ADR_X) {
224                 disassemble_cmd_adr_x(cmdtype, cmdname, word, fgetword(fp), i++);
225             } else {
226                 disassemble_cmd_r(cmdtype, cmdname, word, i);
227             }
228             inst = (cmd != 0x8100) ? true : false;
229         }
230         fprintf(stdout, "\n");
231     }
232     fprintf(stdout, "        END\n");
233     free_cmdtable(HASH_CODE);
234     fclose(fp);
235     return stat;
236 }
237
238 void disassemble_memory(WORD start, WORD end)
239 {
240     WORD cmd = 0;
241     CMDTYPE cmdtype = 0;
242     const char *cmdname = NULL;
243     bool inst = true;
244
245     for(int i = start; i <= end; i++) {
246         cmd = sys->memory[i] & 0xFF00;
247         cmdname = getcmdname(cmd);
248         cmdtype = getcmdtype(cmd);
249         if(sys->memory[i] == 0) {
250             if(inst == true) {  /* プログラム領域の場合  */
251                 disassemble_cmd_r(NONE, "nop", 0, i);
252             } else {            /* データ領域の場合。メモリーでは、DC 0とみなす */
253                 disassemble_dc(0, i);
254             }
255         } else if(cmd == 0) {
256             disassemble_dc(sys->memory[i], i);
257         } else {
258             if(cmdtype == R_ADR_X || cmdtype == ADR_X) {
259                 disassemble_cmd_adr_x(cmdtype, cmdname, sys->memory[i], sys->memory[i+1], i);
260                 i++;
261             } else {
262                 disassemble_cmd_r(cmdtype, cmdname, sys->memory[i], i);
263             }
264             inst = (cmd != 0x8100) ? true : false;
265         }
266         fprintf(stdout, "\n");
267     }
268 }