逆アセンブルのリファクタリング
[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 cmdtype コマンドの種類
78  * @param *cmdname コマンドの名前
79  * @param word ワード値
80  * @param adr アドレス値
81  * @param pradr 次に実行すべき命令語の先頭アドレス
82  */
83 void disassemble_dc(WORD word, WORD pradr);
84
85 void disassemble_puts_code(int ascol, WORD pradr, int wordc, WORD wordv[])
86 {
87     int i;
88     for(i = 0; i < codecol-ascol; i++){
89         fprintf(stdout, " ");
90     }
91     if(wordc == 1) {
92         fprintf(stdout, "; #%04X: #%04X", pradr, wordv[0]);
93     } else if(wordc == 2) {
94         fprintf(stdout, "; #%04X: #%04X #%04X", pradr, wordv[0], wordv[1]);
95     }
96 }
97 void disassemble_cmd_adr_x(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD adr, WORD pradr)
98 {
99     WORD x;
100     char *g;
101     int cnt = 0;
102     cnt += fprintf(stdout, "        %-7s ", cmdname);
103     if(cmdtype == R_ADR_X) {
104         cnt += fprintf(stdout, "%s,", g = grstr((word & 0x00F0) >> 4));
105         FREE(g);
106     }
107     cnt += fprintf(stdout, "#%04X", adr);
108     if((x = (word & 0x000F)) != 0) {
109         cnt += fprintf(stdout, ",%s", g = grstr(x));
110         FREE(g);
111     }
112     disassemble_puts_code(cnt, pradr, 2, (WORD []){word, adr});
113 }
114
115 void disassemble_cmd_r(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD pradr)
116 {
117     char *g, *g1, *g2;
118     int cnt = 0;
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     cnt = fprintf(stdout, "        DC      %-5d ", word);
138     disassemble_puts_code(cnt, pradr, 1, (WORD []){word});
139     fprintf(stdout, " ::" );
140     print_dumpword(word, true);
141 }
142
143 void disassemble_ds(WORD wcnt, WORD pradr)
144 {
145     int cnt = 0, i;
146     cnt = fprintf(stdout, "        DS      %-5d ", wcnt);
147     disassemble_puts_code(cnt, pradr, 1, (WORD []){0});
148     for(i = 0; i < wcnt - 1; i++) {
149         fprintf(stdout, "\n");
150         disassemble_puts_code(0, pradr+1, 1, (WORD []){0});
151     }
152 }
153
154 WORD fgetword(FILE *stream)
155 {
156     WORD aword;
157     fread(&aword, sizeof(WORD), 1, stream);
158     return aword;
159 }
160
161 void fungetword(FILE *stream)
162 {
163     fseek(stream, -sizeof(WORD), SEEK_CUR);
164 }
165
166 WORD zero_data_cnt(FILE *stream)
167 {
168     WORD cnt = 0, word = 0;
169     while(!feof(stream) && word == 0) {
170         word = fgetword(stream);
171         cnt++;
172     }
173     if(!feof(stream)) {
174         fungetword(stream);
175     }
176     return cnt;
177 }
178
179 bool disassemble_file(const char *file)
180 {
181     bool stat = true;
182     FILE *fp;
183     WORD i = 0, word, cmd, zcnt;
184     CMDTYPE cmdtype = 0;
185     char *cmdname;
186     bool inst = true;
187
188     assert(file != NULL);
189     if((fp = fopen(file, "rb")) == NULL) {
190         perror(file);
191         return false;
192     }
193
194     create_code_cmdtype();                          /* 命令のコードとタイプがキーのハッシュ表を作成 */
195
196     fprintf(stdout, "MAIN    START\n");
197     for(word = fgetword(fp); !feof(fp); i++, word = fgetword(fp)) {
198         cmdname = getcmdname(cmd = word & 0xFF00);
199         cmdtype = getcmdtype(cmd);
200         if(word == 0){
201             if(inst == true) {  /* プログラム領域の場合  */
202                 disassemble_cmd_r(NONE, "nop", 0, i);
203             } else {            /* データ領域の場合 */
204                 if((zcnt = zero_data_cnt(fp)) == 1) { /* 1つだけの0はDCとみなす */
205                     disassemble_dc(0, i);
206                 } else {        /* 連続する0はDSとみなす */
207                     disassemble_ds(zcnt, i);
208                     i += zcnt - 1;
209                 }
210             }
211         } else if(cmd == 0) {
212             disassemble_dc(word, i);
213         } else {
214             if(cmdtype == R_ADR_X || cmdtype == ADR_X) {
215                 disassemble_cmd_adr_x(cmdtype, cmdname, word, fgetword(fp), i++);
216             } else {
217                 disassemble_cmd_r(cmdtype, cmdname, word, i);
218             }
219             inst = (cmd != 0x8100) ? true : false;
220         }
221         fprintf(stdout, "\n");
222     }
223     fprintf(stdout, "        END\n");
224     free_code_cmdtype();
225     fclose(fp);
226     return stat;
227 }
228
229 void disassemble_memory(WORD start, WORD end)
230 {
231     WORD i, word, cmd;
232     CMDTYPE cmdtype = 0;
233     char *cmdname;
234     bool inst = true;
235
236     for(i = start; i <= end; i++) {
237         word = sys->memory[i];
238         cmdname = getcmdname(cmd = word & 0xFF00);
239         cmdtype = getcmdtype(cmd);
240         if(word == 0) {
241             if(inst == true) {  /* プログラム領域の場合  */
242                 disassemble_cmd_r(NONE, "nop", 0, i);
243             } else {            /* データ領域の場合。メモリーでは、DC 0とみなす */
244                 disassemble_dc(0, i);
245             }
246         } else if(cmd == 0) {
247             disassemble_dc(word, i);
248         } else {
249             if(cmdtype == R_ADR_X || cmdtype == ADR_X) {
250                 disassemble_cmd_adr_x(cmdtype, cmdname, word, sys->memory[i+1], i);
251                 i++;
252             } else {
253                 disassemble_cmd_r(cmdtype, cmdname, word, i);
254             }
255             inst = (cmd != 0x8100) ? true : false;
256         }
257         fprintf(stdout, "\n");
258     }
259 }